كتابات:
IMPORTANT NOTE: These snippets is a direct snippets. Please make sure to use dependency injection always to make sure to follow the standards and to make your code testable later on.
// Execute command in all subfolders. for d in ./*/ ; do (cd "$d" && touch hi.txt); done for i in {1..33}; do (lando drush dcer taxonomy_term $i --folder=modules/custom/ddd_default_content/content); done // Execute command in a specific subfolders. for d in "folder1" "folder2"; do (cd "$d" && touch hi-d.txt); done // Execute using a function. testfunction1() { cd "$1" && touch "$2" && cd .. } testfunction1 foldername filename.txt // Registry rebuild. If you just moved module folder and you need Drupal to read the new one. drush ev "drupal_flush_all_caches();" drush cr // Lando docker network issues, happen sometimes after update: docker network prune
// 20220623 // Extend Drupal class and respecting the Backward compatibility. We should obey the Backward Compatibility when we extend Drupal classes. We may need to think if Drupal class injected a new service and our class has overrides the constructor function. Please read this resource: https://www.previousnext.com.au/blog/safely-extending-drupal-8-plugin-classes-without-fear-of-constructor-changes And review `Search API` contrib module implementation of that: - Class `IndexClearConfirmForm` : [link](https://git.drupalcode.org/project/search_api/-/blob/1c48ee20c78e9d1091db24b449b7987994c450b7/src/Form/IndexClearConfirmForm.php#L23) - Class `IndexController` : [link](https://git.drupalcode.org/project/search_api/-/blob/6914422ea083ec41b5c471f74808d5d17ca9515b/src/Controller/IndexController.php#L43)
// Things we do regularly. // 1. Hide the draggable table rows. ? // 1. Restrict access to revision information from node form. if (isset($form['revision_information'])) { $form['revision_information']['#access'] = FALSE; } if (isset($form['revision_log'])) { $form['revision_log']['#access'] = FALSE; } if (isset($form['revision'])) { $form['revision']['#access'] = FALSE; }
// 20190110 // Drupal 8 generate uuid. $uuid = \Drupal::service('uuid')->generate(); // Drupal form clean values array. $values = $form_state->cleanValues()->getValues(''); // Getting node author uid. $node->getOwnerId(); // Checks whether a string appears to be in the format of a UUID. use Drupal\Component\Uuid\Uuid; Uuid::isValid($uuid_to_validate); // Install new drupal 8 necessary contrib modules. composer require drupal/admin_toolbar drupal/adminimal_theme drupal/rename_admin_paths // Published constant value. NodeInterface::PUBLISHED NodeInterface::PROMOTED NodeInterface::STICKY NodeInterface::NOT_PUBLISHED NodeInterface::NOT_PROMOTED NodeInterface::NOT_STICKY // Install Drupal console. composer require drupal/console --optimize-autoloader
// Views hook orders: // Source: https://www.drupal.org/project/views/issues/1329438#comment-13020162 views_plugins views_data views_data_alter views_plugins_alter views_default_views_alter views_pre_view views_pre_build views_query_alter views_query_substitutions views_post_build views_pre_execute views_post_execute views_pre_render views_post_render
// Views hooks preprocess execution order. // Source: https://drupal.stackexchange.com/a/180714/24113 hook_preprocess_views_view hook_preprocess_views_view_field hook_preprocess_views_view_fields hook_preprocess_views_view_grid hook_preprocess_views_view_table hook_preprocess_views_view_unformatted hook_preprocess_views_view_list
// howto change your drupal HTML markup to not be like the default Drupal website. // Add this line to your settings.php file. (MAKE SURE YOU ARE DOING THIS NOT ON A LIVE WEBSITE) // This line will change /sites/default/files folder and make it /uploads. $settings['file_public_path'] = 'uploads'; // You may want to remove Generator meta tag. https://drupal.stackexchange.com/a/226781
// drupal 8 load term by custom field $term = current(\Drupal::entityTypeManager()->getStorage('taxonomy_term') ->loadByProperties(['field_CUSTOM_NAME' => 'THE_VALUE', 'vid' => 'VOCABULARY_MACHINE_NAME']) ); // Load term by tid. Load taxonomy term. $term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);
// Drupal 8 fetch taxonomy term custom field from term object. print $term->get('field_CUSTOM_NAME')->getValue()[0]['value']; print $term->get('tid')->getValue()[0]['value']; print $term->get('vid')->getValue()[0]['target_id']; print term->get('name')->getValue()[0]['value'];
// Taxonomy term save multiple values. $VALUES = $term->get('field_CUSTOM_NAME')->getValue(); $VALUES[]['value'] = 'NEW VALUE'; $term->field_CUSTOM_NAME->setValue($VALUES);
// Drupal 8 save and get load cookie. use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Cookie; $SymfonyResponse = new Response(); $cookie = new Cookie('YOUR_COOKIE_KEY', 'VALUE_HERE_PLEASE', 0, '/' , NULL, FALSE); $SymfonyResponse->headers->setCookie($cookie); $SymfonyResponse->send(); // Load cookie. $request_cookie = \Drupal::request()->cookies->all(); print $request_cookie['YOUR_COOKIE_KEY'];
// Drupal 8 get user IP. $current_ip = \Drupal::request()->getClientIp();
// Drupal8 save node programmatically. $node = Node::create([ 'type' => 'article', 'title' => 'TITLE_HERE', 'field_category' => [ 'target_id' => 'TID' ], ]); $node->save();
// 20190115 // Drupal 8 read request headers for current user request and get header values. use Symfony\Component\HttpFoundation\ServerBag; $headers = new ServerBag($_SERVER); $headers = $headers->getHeaders(); print_r($headers);
// Drupal 8 load nodes by custom Taxonomy field. $nodes = \Drupal::entityTypeManager() ->getStorage('node') ->loadByProperties(['type' => 'CONTENT_TYPE', 'field_CUSTOM_TERM_REF_FIELD' => $tid]);
// Drupal8 load all nodes from a specific content type. $nids = \Drupal::entityQuery('node')->condition('type','CONTENT_TYPE')->execute(); $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
// 20190308 Bali // Loading current user details. $user = User::load(\Drupal::currentUser()->id());
// 20190308 // Getting and load nodes related to a specific user using entityQuery. $query = \Drupal::entityQuery('node') ->condition('status', 1) //published or not ->condition('type', 'CONTENT_TYPE') //content type ->condition('uid', \Drupal::currentUser()->id()) //content type ->pager(10); //specify results to return $nids = $query->execute(); // Using entityTypeManager. $nodes = \Drupal::entityTypeManager() ->getStorage('node') ->loadByProperties(['type' => 'CONTENT_TYPE', 'uid' => \Drupal::currentUser()->id()]);
// 20190308 // Load file URL from file field value. $fid = $entity->get('field_IMAGE')->getValue()[0]['target_id']; $file = \Drupal\file\Entity\File::load($fid); $image_url = $file->url(); // $image_url = file_create_url($file->getFileUri()); // Getting styled URL from drupal 8 custom image field. $fid = $entity->get('field_IMAGE')->getValue()[0]['target_id']; $file = \Drupal\file\Entity\File::load($fid); $image_uri = $file->getFileUri(); $styled_url = ImageStyle::load('large')->buildUrl($image_uri);
// 20190617 // Page cache can not be controlled by max-age or contexts for anyonymous. You can prevent that kind of caching by using this method to avoid caching for the page or prevent caching in forms. // Source: https://drupal.stackexchange.com/a/219583/24113 \Drupal::service('page_cache_kill_switch')->trigger();
// 20190619 // Save user programmatically. $language = \Drupal::languageManager()->getCurrentLanguage()->getId(); $new_user = User::create(); // Mandatory. $new_user->setPassword('PASSWORD_AS_TEXT'); $new_user->enforceIsNew(); $new_user->setEmail('[email protected]'); $new_user->setUsername('USER_NAME'); // Optional. $new_user->set('init', '[email protected]'); $new_user->set('langcode', $language); $new_user->set('preferred_langcode', $language); $new_user->set('preferred_admin_langcode', $language); $new_user->addRole('ROLE_NAME'); // Set out custom values. $new_user->set('field_CUSTOM', 'VALUE'); $new_user->activate(); _user_mail_notify('register_no_approval_required', $new_user); user_login_finalize($new_user); \Drupal::messenger()->addStatus($this->t('Registration successful. You are now logged in.')); $form_state->setRedirect('');
// 20190619 // Load user by specific custom field. $id_number_check = \Drupal::entityQuery('user') ->condition('status', 1) // ->condition('roles', 'ROLE_NAME') // ->condition('roles',['ROLE_NAME_1', 'ROLE_NAME_2'], 'IN') // ->condition('status', 1) // ->sort('uid', 'ASC') // ->range(0, 1) ->condition('field_NAME', 'VALUE') ->execute();
// 20190626 // Save taxonomy programmatically. use Drupal\taxonomy\Entity\Term; $term = Term::create([ 'name' => 'test', 'vid' => 'client', ]); $term->save(); print $term->id();
// 20190702 // Since `format_date` is deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. // using Drupal time service. $time_value = \Drupal::time()->getCurrentTime(); print \Drupal::service('date.formatter')->format($time_value, 'long'); // Using DrupalDateTime class. use Drupal\Core\Datetime\DrupalDateTime; // Getting site default timezone value. $timezone = Drupal::config('system.date')->get('timezone')['default']; // User default timezone is: drupal_get_user_timezone(). // Instead of time() use this next line. $time_value = \Drupal::time()->getCurrentTime(); $date_original = DrupalDateTime::createFromTimestamp($time_value, $timezone); print $date_original->getTimestamp(); print $date_original->format('Y-m-d\TH:i:s'); // Drupal 8 strtotime $timezone = Drupal::config('system.date')->get('timezone')['default']; $time_value = \Drupal::time()->getCurrentTime(); $date_original = DrupalDateTime::createFromTimestamp($time_value, $timezone); print strtotime('+1 day', $date_original->getTimestamp());
// 20190703 // Generate URL as HTML in Drupal 8 // Always it's better to use fromRoute() instead of fromUri() to make sure to include the language prefix in the URL. $register_link_from_uri = render(Link::fromTextAndUrl('Register', Url::fromUri('base:user/register', ['attributes' => ['class' => 'extra-link-register']]))->toRenderable()); $register_link_from_route = render(Link::fromTextAndUrl('Register', Url::fromRoute('user.register', [], ['attributes' => ['class' => ['extra-link-register']]]))->toRenderable()); $password_link_from_route = render(Link::fromTextAndUrl(t('Reset your password'), Url::fromRoute('user.pass', [], ['attributes' => ['class' => ['extra-link-reset-password']]]))->toRenderable()); print $password_link_from_route; // Will print HTML code of rendered link. // External URL as string. $url = Url::fromUri('https://www.example.com/'); $link = Link::fromTextAndUrl('URL_TEXT_HERE', $url); print $link->toString(); // Form redirect to a view route. $url = Url::fromRoute('view.VIEW_MACHINE_NAME.DISPLAY_MACHINE_NAME', [ 'node' => $node->id(), ]); $form_state->setRedirectUrl($url); // New request link going to node 1 view page :) $add_new = render(Link::fromTextAndUrl(t('New request'), Url::fromRoute('entity.node.canonical', ['node' => 1], [ 'attributes' => [ 'class' => [ 'button', 'button--primary', ], ], ]))->toRenderable());
// 20190715 // Getting content moderation state value. $moderation_state = $node->get('moderation_state')->getValue(); $moderation_state = $moderation_state[0]['value'];
// 20190715 // Redirect to a specific route. $url = Url::fromRoute('view.VIEW_MACHINE_NAME.DISPLAY_MACHINE_NAME', [ 'node' => $node->id(), ])->toString(); $response = new RedirectResponse($url); $response->send(); // Getting the URL as plain text full URL $url = Url::fromRoute('view.VIEW_MACHINE_NAME.DISPLAY_MACHINE_NAME', [ 'node' => $node->id(), ], ['absolute' => TRUE])->toString();
// 20190715 // Load all referenced entities from a multi valued field. // For example this is a reference field to taxonomy terms. // https://gorannikolovski.com/blog/how-loop-through-referenced-entities $node->get('field_NAME')->referencedEntities();
// 20190715 // Alter view fields output. /** * Implements hook_views_pre_render(). */ function HOOK_views_pre_render(ViewExecutable $view) { if (($view->id() == 'VIEW_NAME') && ($view->current_display == 'DISPLAY_NAME')) { foreach ($view->result as $key => &$row) { print_r(json_decode(json_encode($row))); print $row->_entity->id(); // Fetch the entities from the relationship. foreach ($row->_relationship_entities as $entity) { print $entity->id(); } // Exit to view field keys extracted from $row. exit; // Alter view field. $row->node_field_data_title = 'TEST TITLE VALUE'; } } }
// 20190715 // Drupal 8 alter nothing field in views. Alter views fields before output. /** * Implements template_preprocess_views_view_fields(). */ function MODULENAME_preprocess_views_view_field(&$vars) { // Print all available fields. foreach ($vars['view']->field as $key => $field) { // We will print the field name. print $key . '<HR>'; } exit; // To access current row entity. $entity = $vars['row']->_entity; $entity_id = $entity->id(); // To access entities from relationship. $entities = $vars['row']->_relationship_entities; // When you find your field key use this code below. if(isset($vars['view']) && ($vars['view']->id() == 'VIEW_MACHINE_NAME') && ($vars['view']->current_display == 'DISPLAY_MACHINE_NAME')) { if (isset($vars['view']->field) && (count($vars['view']->field) > 0)) { // if ($vars['field']->field == 'YOUR_FIELD_NAME') if ($vars['field']->field == 'nothing') { $vars['output'] = 'TEST_CUSTOM_VALUE'; } } } }
// 20190717 // Render image as HTML. Render img as HTML output. $file_id = '1111'; $image_file = \Drupal\file\Entity\File::load($file_id); $image_uri = $image_file->getFileUri(); $build = [ '#theme' => 'image_style', '#style_name' => 'thumbnail', '#uri' => $image_uri, ]; /** @var \Drupal\Core\Render\Renderer $renderer */ $renderer = \Drupal::service('renderer'); $img_html = $renderer->render($build); print $img_html;
// Drupal 8 Remove title from the node view. Remove any field from a specific rendered node view mode. // You can also override the display options by using getComponent() and setComponent() from EntityDisplayBase class. /** * Implements hook_entity_view_display_alter(). */ function MODULENAME_entity_view_display_alter(\Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, array $context) { if (isset($context['entity_type']) && ($context['entity_type'] == 'node') && isset($context['bundle']) && ($context['bundle'] == 'CONTENT_TYPE') && isset($context['view_mode']) && ($context['view_mode'] == 'VIEW_MODE')) { // teaser, full .. $display->removeComponent('title'); $display->removeComponent('field_NAME'); // Still, I'm trying to remove only the title link :) // keywords: drupal 8 remove link from title field display link_to_entity. } }
// 20190718 // Load paragraph entity from node object. if ($node->field_PARAGRAPH_FIELD) { foreach ($node->field_PARAGRAPH_FIELD as $item) { $paragraph = Paragraph::load($item->target_id); } }
// Force using specific form view mode. /** * Implements hook_entity_type_alter(). */ function MODULENAME_entity_form_display_alter(&$form_display, $context) { // Check the specific content type that we are targeting. if (isset($context['entity_type']) && isset($context['bundle']) && ($context['entity_type'] == 'node') && ($context['bundle'] == 'CONTENT_TYPE_MACHINE_NAME')) { // Get the current user. $user = \Drupal::currentUser(); // Force our custom view mode if the current user is not having this permission. if (!$user->hasPermission('CUSTOM PERMISSION')) { $storage = \Drupal::service('entity_type.manager')->getStorage('entity_form_display'); $form_display = $storage->load('node.CONTENT_TYPE_MACHINE_NAME.VIEW_MODE_MACHINE_NAME'); } } // Force using a specific view mode in user form if user does not have a specific permission. if (isset($context['entity_type']) && isset($context['bundle']) && ($context['entity_type'] == 'user') && ($context['bundle'] == 'user')) { // Get the current user. $user = \Drupal::currentUser(); // Force our custom view mode if the current user is not developer. if (!$user->hasPermission('CUSTOM PERMISSION')) { $storage = \Drupal::service('entity_type.manager')->getStorage('entity_form_display'); $form_display = $storage->load('user.user.VIEW_MODE_MACHINE_NAME'); } } }
// 20190721 // Force a specific view mode on entity display page. /** * Implements hook_entity_view_mode_alter(). */ function MODULENAME_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInterface $entity, $context) { // Check the specific entity type that we are targeting. if (($entity->getEntityTypeId() == 'user') && ($entity->bundle() == 'user') && ($view_mode == 'full')) { // Get the current user. $user = \Drupal::currentUser(); // Force our custom view mode if the current user does not have a specific permission. if (!$user->hasPermission('PERMISSION NAME')) { // Make sure to enable the (compact) view mode of the user from /admin/config/people/accounts/display $view_mode = 'compact'; } } // Same code but for specific content type. if (($entity->getEntityTypeId() == 'node') && ($entity->bundle() == 'CONTENT_TYPE_MACHINE_NAME') && ($view_mode == 'full')) { } }
// drupal 8 alter view mode field value. // Create a virtual field when display an entity. /** * Implements hook_entity_view_alter(). */ function MODULENAME_entity_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) { if (($display->getTargetEntityTypeId() == 'node') && ($display->getTargetBundle() == 'CONTENT_TYPE_MACHINE_NAME') && ($display->getOriginalMode() == 'VIEW_MODE')) { $build['field_virtual'] = [ '#markup' => 'HEEEY!', '#weight' => 99, ]; } // Check if this is our targeted view. if (($display->getOriginalId() == 'user.user.full') && ($display->getEntityTypeId() == 'entity_view_display')) { print $display->getOriginalId(); print '<HR>'; print $display->getTargetEntityTypeId(); print '<HR>'; print $display->getOriginalMode(); print '<HR>'; print $display->getEntityTypeId(); print '<HR>'; print $display->getTargetBundle(); exit; } }
// 20190728 // Update node and save it as a new revision. $node->set('field_test', $value); // Making sure to save this update as a new revision. $node->setNewRevision(TRUE); $node->revision_log = 'write_log_message_here'; $node->setRevisionCreationTime(REQUEST_TIME); $node->setRevisionUserId(\Drupal::currentUser()->id()); $node->save();
// 20190730 // drupal 8 template_preprocess_views_view alter row markup.
// 20190731 // Tempstore. // Source: http://karimboudjema.com/en/drupal/20190315/saving-temporary-values-form-private-tempstore-drupal-8 tempstore.private // 1. Get the private tempstore factory, inject this in your form, controller or service. $tempstore = \Drupal::service('tempstore.private'); // Get the store collection. $store = $tempstore->get('my_module_collection'); // Set the key/value pair. $store->set('key_name', $value); // 2. Get the value somewhere else in the app. $tempstore = \Drupal::service('tempstore.private'); // Get the store collection. $store = $tempstore->get('my_module_collection'); // Get the key/value pair. $value = $store->get('key_name'); // Delete the entry. Not mandatory since the data will be removed after a week. $store->delete('key_name'); // -- // Deprecated services $tempstore = \Drupal::service('user.private_tempstore')->get('my_module_name'); $tempstore = \Drupal::service('tempstore.shared')->get('my_module_name'); // Source: https://www.drupal.org/node/2935639
// 20190820 // Load field info .. load field settings ... field config info // Get paragraph field type (file) file_extensions from field instance. $field_instance = \Drupal::entityTypeManager()->getStorage('field_config')->load('paragraph.PARAGRAPH_TYPE_NAME.field_NAME'); $settings = $field_instance->getSettings(); print $settings['file_extensions']; $field_instance = \Drupal::entityTypeManager()->getStorage('field_config')->load('node.CONTENT_TYPE.field_NAME'); $field_instance = \Drupal::entityTypeManager()->getStorage('field_config')->load('user.user.field_NAME');
// 20190829 // Auto import languages. // Add these two lines to your module .info file. 'interface translation project': MODULE_NAME 'interface translation server pattern': modules/custom/MODULE_NAME/translations/%project-%language.po // The .po file should be exists inside your module. // Don't miss to configure your Import behavior on: /admin/config/regional/translate/settings // Import from UI: /admin/reports/translations // Drush command: // drush locale-check && drush locale-update && drush cr // @NOTE: It is not a good idea to do this if you are working on your contrib module since the translation files should be on a separate folder. (Thanks mhmd Gomma) // For more info please review these two lines: https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/locale/locale.api.php#L30 https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/locale/locale.api.php#L55
// 20190829 // Get site name $site_name $site_name = Drupal::config('system.site')->get('name'); print $site_name;
// 20190924 // Delete field programmatically. use Drupal\field\Entity\FieldStorageConfig; $field = FieldStorageConfig::loadByName('taxonomy_term', 'field_tr_title'); if ($field) { // Delete this field. $field->delete(); } else { // The field can not be loaded or maybe it does not exist. }
// 20191010 // Invalidate cached rendered context. Cache::invalidateTags(['rendered']);
// 20191222 // Getting private file URL as a string. $fid = 1; $file = File::load($fid); $file_uri = $file->getFileUri(); $file_name = $file->getFilename(); $stream = \Drupal::service('stream_wrapper_manager')->getViaUri($file_uri); $file_url = $stream->getExternalUrl();
// 20200318 // Drupal entityQuery Query isNull. how to check if query field value is null. // is to use ->notExists(). This will get the NULL values for you. Even if the value was saved before then was emptied after that. $nodes = \Drupal::entityQuery('node') ->condition('type', 'CONTENT_TYPE_NAME') ->condition('field_CUSTOM_ONE', 'VALUE') ->notExists('field_CUSTOM_TWO') ->execute(); if (is_array($nodes) && (count($nodes) > 0)) { print_r($nodes);exit; foreach ($nodes as $nid) { $node = Node::load($nid); } }
// 20201218 // Getting base URL $host = \Drupal::request()->getHost(); $host = \Drupal::request()->getSchemeAndHttpHost(); // Source: https://drupal.stackexchange.com/a/202811/24113
// Loading field settings. // $field_definition = FieldConfig::loadByName($entity_type, $bundle, $field_name); $field_definition = FieldConfig::loadByName('paragraph', 'PARAGRAPH_MACHINE_NAME', 'FIELD_CUSTOM'); $field_allowed_values_array = $field_definition->getSettings()['allowed_values'];
// Check if user has specific access. user access user_access() // Source: https://www.drupal.org/node/2049309 \Drupal::currentUser()->hasPermission('name of permission'); // OR $account = \Drupal\user\Entity\User::load(3); $account->hasPermission('name of permission');
// 20211025 // Get all blocks IDs. Get block id value print_r(array_keys(\Drupal::service('plugin.manager.block')->getDefinitions()));
// 20220105 // settings.local.php for development environment $settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml'; $settings['cache']['bins']['render'] = 'cache.backend.null'; $settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null'; $settings['cache']['bins']['page'] = 'cache.backend.null'; $settings['extension_discovery_scan_tests'] = FALSE; $config['system.performance']['css']['preprocess'] = FALSE; $config['system.performance']['js']['preprocess'] = FALSE; $config['system.logging']['error_level'] = 'verbose'; # development.services.yml parameters: twig.config: debug: true # FULL parameters: session.storage.options: { gc_probability: 1, gc_divisor: 100, gc_maxlifetime: 200000, cookie_lifetime: 2000000 } twig.config: { debug: true, auto_reload: true, cache: false } renderer.config: { required_cache_contexts: ['languages:language_interface', theme, user.permissions], auto_placeholder_conditions: { max-age: 0, contexts: [session, user], tags: { } } } http.response.debug_cacheability_headers: true factory.keyvalue: { } factory.keyvalue.expirable: { } filter_protocols: [http, https, ftp, news, nntp, tel, telnet, mailto, irc, ssh, sftp, webcal, rtsp] cors.config: { enabled: false, allowedHeaders: { }, allowedMethods: { }, allowedOrigins: ['*'], exposedHeaders: false, maxAge: false, supportsCredentials: false } services: cache.backend.null: class: Drupal\Core\Cache\NullBackendFactory # 9.1 renderer.config: required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions'] auto_placeholder_conditions: max-age: 0 contexts: ['session', 'user'] tags: [] debug: true
// 20220108 // Render view programmatically. $view = \Drupal\views\Views::getView('VIEW_NAME'); $view->setDisplay('DISPLAY_NAME'); $view->setArguments([]); $view->execute(); $result = $view->buildRenderable('DISPLAY_NAME', []); $result = render($result);
// 20220108 // Set view filter programmatically. use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\query\QueryPluginBase; /** * Implements hook_views_query_alter(). */ function HOOK_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { if (($view->id() == 'VIEW_NAME') && ($view->current_display == 'DISPLAY_NAME')) { foreach ($query->where as &$condition_group) { foreach ($condition_group['conditions'] as &$condition) { // Ignore some conditions. if (in_array($condition['field'], ['node_field_data.status', 'node_field_data.type'])) { continue; } if ($condition['field'] == 'taxonomy_term_field_data_taxonomy_term__parent_1.tid') { $condition = [ 'field' => 'taxonomy_term_field_data_taxonomy_term__parent_1.tid', 'value' => (1, 2, 3), 'operator' => 'IN', ]; } } } } }
// 20220108 // TWIG TRIM {{ data.description.plain|truncate(8, true, true) }} // TWIG class name {{ data.machine_name|clean_class }} {% if not logged_in %} {% include '@THEMENAME/page--anonymous.html.twig' %} {% else %} {% include '@THEMENAME/page--authenticated.html.twig' %} {% endif %}
// 20220124 // Twig absolute URL {{ drupal_url(active_theme_path() ~ '/images/avatar.png', {absolute: true}) }} {{ drupal_url('/login', {absolute: true}) }} {{ drupal_url('/list/' ~ data.id ~ '/' ~ data.machine_name ~ '/all', {absolute: true}) }} {{ drupal_url(path('ROUTE.NAME_HERE', {'PARAM1': data.value, 'PARAM2': data.id}), {absolute: true}) }}
// 20220124 // menu.html.twig {% import _self as menus %} {{ menus.menu_links(items, attributes, 0, menu_name) }} {% macro menu_links(items, attributes, menu_level, menu_name) %} {% import _self as menus %} {% if items %} {% if menu_level == 0 %}
-
{% else %}
- {{ link(item.title, item.url, { 'class': classes_link }) }} {% if item.below %} {{ menus.menu_links(item.below, attributes, menu_level + 1) }} {% endif %} {% endfor %}
-
{% endif %}
{% for item in items %}
{%
set classes_link = [
'nav-link',
item.is_expanded ? 'dropdown-toggle',
item.is_collapsed ? 'dropdown-toggle',
item.in_active_trail ? 'active',
]
%}
// Check if file private or public. $stream_wrapper = \Drupal::service('file_system')->uriScheme($file_object->getFileUri()) D9: $stream_wrapper = \Drupal::service('stream_wrapper_manager')->getScheme($file_object->getFileUri());
// 20220212 // Get and save remote file inside node file field. $file_url = 'FILE_URL_HERE'; $filename = pathinfo($file_url); $new_filename = 'imported-' . $filename['filename']; $new_file_folder_uri = 'private://import'; $new_file_uri = $new_file_folder_uri . '/' . $new_filename . '.jpg'; $file_content = file_get_contents($file_url); // Important step to create folder if not exists. /** @var \Drupal\Core\File\FileSystemInterface $file_system */ $file_system = \Drupal::service('file_system'); $file_system->prepareDirectory($new_file_folder_uri, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); $file = file_save_data($file_content, $new_file_uri); if ($file) { $node = Node::load(1); $node->set('field_logo', $file->id()); $node->save(); } else { // Failed to save the file. } // Check if remote file exists function remoteFileExists($url) { $curl = curl_init($url); curl_setopt($curl, CURLOPT_NOBODY, true); $result = curl_exec($curl); $ret = false; if ($result !== false) { // if request was ok, check response code $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($statusCode == 200) { $ret = true; } } curl_close($curl); return $ret; }
// 20220214 // Getting theme path programmatically. /** @var \Drupal\Core\Extension\ThemeHandler $theme_handler */ $theme_handler = \Drupal::service('theme_handler'); $default_theme = $theme_handler->getDefault(); $specific_theme_path = $theme_handler->getTheme('THEME_NAME')->getPath(); /** @var \Drupal\Core\Theme\ThemeManager $theme_manager */ $theme_manager = \Drupal::theme(); /** @var \Drupal\Core\Theme\ActiveTheme $active_theme */ $active_theme = $theme_manager->getActiveTheme(); global $base_url; $default_user_photo = $base_url.'/'. $active_theme->getPath() .'/images/user.png';
// 20220214 // Getting view row data in view field twig file (views-view-field.html.twig) or (views-view-field--field-nr-workflow.html.twig) {{ view.field.field_nr_workflow.original_value }} {{ view.field.field_nr_workflow.value(view.result[row.index]) }} {{ data.description.plain|slice(0, 60) }} For more: https://www.drupal.org/docs/theming-drupal/twig-in-drupal/discovering-and-inspecting-variables-in-twig-templates
// 20220215 // mobile_number field $allowed_countries['SA'] = 'SA'; $allowed_countries['AE'] = 'AE'; $allowed_countries['BH'] = 'BH'; $allowed_countries['KW'] = 'KW'; $allowed_countries['OM'] = 'OM'; $allowed_countries['QA'] = 'QA'; $form['field_u_mobile']['widget'][0]['#required'] = TRUE; $form['field_u_mobile']['widget'][0]['#default_value']['country'] = 'SA'; $form['field_u_mobile']['widget'][0]['#mobile_number'] = [ 'allowed_countries' => $allowed_countries, 'verify' => \Drupal\mobile_number\MobileNumberUtilInterface::MOBILE_NUMBER_VERIFY_NONE, 'message' => 'Your verification code from !site_name: !code', 'tfa' => FALSE, 'token_data' => [], 'placeholder' => '05xxxxxxxx', ];
// 20220216 // Twig print full URL in Twig template {{ url('view.VIEW_NAME.DISPLAY_NAME', {'arg_0': 1}) }}
// Submit form with no validations // Ignore form validation // '#limit_validation_errors' => array(), $form['actions'] = ['#type' => 'actions']; $form['actions']['back'] = [ '#type' => 'submit', // '#button_type' => 'primary', '#value' => $this->t('Back'), '#submit' => ['::previousForm'], '#limit_validation_errors' => [], '#validate' => [], ];
// 20220310 // Validate email value if (!\Drupal::service('email.validator')->isValid($value)) { $form_state->setError($element, t('The email address %mail is not valid.', ['%mail' => $value])); }
// 20220328 // Hide page title block for specific routes. // Inject Drupal 8 block programmatically. /** * Implements template_preprocess_page(). */ function MYMODULE_preprocess_page(&$variables) { // Hide page title for specific routes. $route_name = \Drupal::routeMatch()->getRouteName(); $routes = [ 'ROUTE_NAME', ]; if (in_array($route_name, $routes)) { unset($variables['page']['content']['THEMENAME_page_title']); } }
// 20220331 // PHPCS lando composer --dev require squizlabs/php_codesniffer lando composer --dev require drupal/coder lando composer --dev require slevomat/coding-standard ./vendor/bin/phpcs --standard=Drupal,DrupalPractice --extensions=php,module,inc,install,test,profile,theme,js,css,info,txt,md --runtime-set installed_paths /app/vendor/drupal/coder/coder_sniffer,/app/vendor/slevomat/coding-standard
// 20220406 // Lando disable annoying update reminders: lando --channel none
// 20220410 // Getting timestamp from a date field value. // Getting date object from date field value. /** @var \Drupal\Core\Datetime\DrupalDateTime $date_object */ $date_object = $node->field_date->date; $date_object->format('Y/m/d'); $date_object->getTimestamp()
// Redirect the page response and respecting the cacheability metadata to avoid "leaked cacheability metadata". $front_url = Url::fromRoute('view.aliens.list', [], ['absolute' => TRUE])->toString(); $response = new \Drupal\Core\Cache\CacheableResponse($front_url, \Symfony\Component\HttpFoundation\Response::HTTP_OK); $response->addCacheableDependency($front_url); return $response;
// 20220419 // Inject twig template inside view header $add_new = [ '#theme' => 'template_name_here', ]; $add_new = render($add_new); $options = [ 'id' => 'area', 'table' => 'views', 'field' => 'area', 'relationship' => 'none', 'group_type' => 'none', 'admin_label' => '', 'empty' => TRUE, 'tokenize' => NULL, 'content' => [ 'value' => $add_new, 'format' => 'raw', // This is the text format you need to have `raw` text format. ], 'plugin_id' => 'text', ]; $view->setHandler($display_id, 'header', 'area', $options);
// cURL $url = ''; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $url, CURLOPT_POST => 1, CURLOPT_POSTFIELDS => [ 'name' => 'hi', ], CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 60, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, //CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_SSL_VERIFYHOST => 0 , CURLOPT_SSL_VERIFYPEER => 0 , CURLOPT_HTTPHEADER => [ 'Authorization: Bearer AA', ], )); $response = curl_exec($curl); $response = json_decode($response); $err = curl_error($curl); curl_close($curl); $client = new \GuzzleHttp\Client(['base_uri' => 'https://api/v4']); $response = $client->request('POST', '/accounts', [ 'headers' => [ 'Authorization' => 'Bearer AAAA', ], 'multipart' => [ [ 'name' => 'file', 'contents' => $file_contents ], ] ]);
// drupal manage private file access /** * Implements hook_entity_access(). */ function hook_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account) { if ($entity->getEntityTypeId() == 'file') { if ($account->hasPermission('developer')) { return AccessResult::allowed(); } } return AccessResult::neutral(); }
// Return #markup in RAW HTML code with no restrictions. use Drupal\Core\Render\Markup; return [ '#markup' => Markup::create($html), ];
// Require JS /libraries into /web/libraries folder 1. `composer require oomphinc/composer-installers-extender` 1. add the following to your composer.json file into the repositories section: ``` { "type": "composer", "url": "https://asset-packagist.org" } ``` 1. It's also needed to extend the 'installer-path' section: ``` "web/libraries/{$name}": [ "type:drupal-library", "type:bower-asset", "type:npm-asset" ], ``` 1. And add a new 'installer-types' section next to the 'installer-path' in the 'extra' section: `"installer-types": [ "bower-asset", "npm-asset" ],` into 1. Now you can download libraries like: `composer install npm-asset/select2` .. you need to pick the right package name, you can browse packages from here: https://asset-packagist.org/ ---- Helpful Resources: - https://www.bounteous.com/insights/2020/04/22/guide-loading-external-javascript-drupal/ - https://www.drupal.org/project/slick/issues/2855190 - Description of select2 contrib module: https://www.drupal.org/node/1638186/revisions/12029663/view - https://git.drupalcode.org/project/webform/-/blob/8.x-5.x/composer.libraries.json - https://www.drupal.org/docs/8/modules/webform/webform-frequently-asked-questions/how-to-use-composer-to-install-libraries - https://github.com/acquia/acquia-ra-composer/blob/master/composer-templates/composer-libraries.json - Different approach: https://github.com/balbuf/drupal-libraries-installer
// drush ev '\Drupal::entityTypeManager()->getStorage("shortcut_set")->load("default")->delete();'