Web Development

  • drupal + docker

    Drupal 8 Docker with multisite setup

    1. Setup Docker Download latest release of Docker4Drupal and install as Vanilla Drupal or to an existing codebase. Follow the comprehensive tutorial from https://wodby.com/docs/1.0/stacks/drupal/local/#usage   2. Update Docker configurations Set the default site domain name in .env  ... PROJECT_BASE_URL=mycoolsite.localhost ...   Create multiple instances of database servers in docker-compose.yml ... default: image: wodby/mariadb:$MARIADB_TAG container_name: "${PROJECT_NAME}_default" stop_grace_period: 30s environment: MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD MYSQL_DATABASE: $DB_NAME MYSQL_USER: $DB_USER MYSQL_PASSWORD: $DB_PASSWORD ports: - 42330:3306 # Port that we can access outside of the container volumes: - ./assets/default.sql:/docker-entrypoint-initdb.d/dump.sql # Place init .sql file(s) here. subsite: image: wodby/mariadb:$MARIADB_TAG container_name: "${PROJECT_NAME}_subsite" stop_grace_period: 30s environment: MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD MYSQL_DATABASE: $DB_NAME MYSQL_USER: $DB_USER MYSQL_PASSWORD: $DB_PASSWORD ports: - 42331:3306 # Port that we can access outside of the container volumes: - ./assets/subsite.sql:/docker-entrypoint-initdb.d/dump.sql # Place init .sql file(s) here. ...   Set web server (nginx) configurations ... nginx: image: wodby/nginx:$NGINX_TAG container_name: "${PROJECT_NAME}_nginx" depends_on: - php environment: NGINX_STATIC_OPEN_FILE_CACHE: "off" NGINX_ERROR_LOG_LEVEL: debug NGINX_BACKEND_HOST: php NGINX_SERVER_ROOT: /var/www/html/web NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET # NGINX_DRUPAL_FILE_PROXY_URL: http://example.com volumes: - ./:/var/www/html:cached ports: - "8001:80" # port to use for proxy labels: - 'traefik.backend=${PROJECT_NAME}_nginx' - 'traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${PROJECT_BASE_URL}' # subdomain ...   3. Drupal site configurations In this tutorial we will have these 2 sites: Default Name: default Domain: mycoolsite.localhost Port: 80001 Subsite Name: subsite Domain: subsite.mycoolsite.localhost Port: 80001     First thing is we need to make changes on sites.php file base on the site informations above.  ... $sites['8001.mycoolsite.localhost'] = 'default'; // Docker default site $sites['8001.subsite.mycoolsite.localhost'] = 'subsite'; // Docker subsite site ...   Next is we need to make sure we have these 2 folders under the sites folder: default subsite   Add the database configurations for both sites using the hostname that we configured from docker-compose.yml.   sites/default/settings.php (default) ... $databases['default']['default'] = [ 'database' => 'drupal', 'username' => 'drupal', 'password' => 'drupal', 'prefix' => '', 'host' => 'default', 'port' => '3306', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', ]; ...   sites/subsite/settings.php (default) ... $databases['default']['default'] = [ 'database' => 'drupal', 'username' => 'drupal', 'password' => 'drupal', 'prefix' => '', 'host' => 'subsite', 'port' => '3306', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', ]; ...    
  • Drupal 8: Set entity field cardinality programatically inside a custom form

    This is how you can dynamically change a multi select entity field maximum number of selected items programmatically. //The sample codes below will get an entity form and render the entity form fields to a custom form. // Create the entity $entity = $this->orderItemStorage->create([ 'title' => 'Order Item', 'type' => 'bee', 'purchased_entity' => 'my_product_variation_id', 'quantity' => 1, 'unit_price' => '100', ]); // Add the entity to form_state $form_state->set('order_item', $entity); // Get the form display $form_display = $this->entityTypeManager->getStorage('entity_form_display')->load('commerce_order_item.bee.add_to_cart'); $form_state->set('order_item_form_display', $form_display); // Set the form parents to empty to avoid form rendering errors $form['#parents'] = []; // loop through the entity form fields foreach ($form_display->getComponents() as $name => $component) { $widget = $form_display->getRenderer($name); if (!$widget) { continue; } $items = $entity->get($name); if ($name === 'my_multiple_select_field') { // Get the field definition and field storage definition object and set the cardinality $definition = $items->getFieldDefinition(); $fieldStorageDefinition = $definition->getFieldStorageDefinition(); $fieldStorageDefinition->setCardinality(1); } $items->filterEmptyItems(); // Add the entity form field to your custom form $form[$name] = $widget->form($items, $form, $form_state); $form[$name]['#access'] = $items->access('edit'); }  
  • drupal 8

    Drupal 8: Redirect to page from Event Subscriber with destination query

    Create your Event Subscriber Create your module's services yml file and declare the event subscriber services: mymodule.autologin: class: Drupal\mymodule\EventSubscriber\AutoLogin tags: - {name: event_subscriber} Save this as mymodule.services.yml inside mymodule folder Create the actual class used from above code <?php namespace Drupal\mymodule\EventSubscriber; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class AutoLogin implements EventSubscriberInterface { public function redirectToLogin() { // PUT YOUR LOGIC HERE } /** * {@inheritdoc} */ public static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = ['redirectToLogin']; return $events; } } Save this as AutoLogin.php inside mymodule/src/EventSubscriber folder   Redirect using URL::fromRoute with destination query $current_path = \Drupal::service('path.current')->getPath(); $url = \Drupal\Core\Url::fromRoute('simplesamlphp_auth.saml_login', [], ['query' => ['destination' => $current_path, 'absolute' => TRUE]]); $response = new RedirectResponse($url->toString(), 302); $event->setResponse($response); Put the above code in the AutoLogin::redirectLogin(). This code will get the current path and redirect to saml login page to auto login, then if the login is successful, it will redirect to the original path that we are trying to access.  
  • drupal + bootstrap

    Drupal 8 module: Bootstrap 4 Modal

    Are you using Drupal 8 Bootstrap 4 Theme (Barrio) and you want to use Drupal Ajax Dialog? Chances are you might have to do some extra coding just to make that Drupal core modal dialog make it look and feel like a bootstrap modal. Bootstrap 4 Modal module adds new type of dialog that you can use. Example of Drupal core ajax modal dialog: <a class="use-ajax" data-dialog-options="{&quot;width&quot;:400}" data-dialog-type="modal" href="/node/1"> First node displayed in core modal dialog. </a> This link will load drupal node id 1 by ajax on drupal core modal dialog with 400px width   Example of Bootstrap 4 Modal dialog: <a class="use-ajax" data-dialog-options="{&quot;dialogClasses&quot;:&quot;modal-dialog-centered&quot;,&quot;dialogShowHeader&quot;:false}" data-dialog-type="bootstrap4_modal" href="/node/1"> First node displayed in bootstrap 4 modal dialog. </a> This link will load drupal node id 1 by ajax on drupal core modal dialog with modal dialog vertically centered and no modal header.  
  • Guide to configure KDiff3 as git merge tool and diff tool (Mac)

    This is a simple guide to configure your git merge tool and diff tool to use KDiff3. Install KDiff3  https://sourceforge.net/projects/kdiff3/files/ Configure Git Execute in terminal git config --add merge.tool kdiff3 git config --add mergetool.kdiff3.path /Applications/kdiff3.app/Contents/MacOS/kdiff3 git config --add mergetool.kdiff3.trustExitCode false git config --add diff.guitool kdiff3 git config --add difftool.kdiff3.path /Applications/kdiff3.app/Contents/MacOS/kdiff3 git config --add difftool.kdiff3.trustExitCode false  
  • Using Drupal 8 Structure Sync Module

    Structure Sync module is a great tool that helps you import/export your site's contents like Taxonomy, Menu and Blocks. Installation Download the latest version from https://www.drupal.org/project/structure_sync or by using composer: composer require drupal/structure_sync Then go to Extend and install Structure Sync module or by drush: vendor/bin/drush en structure_sync --uri=default   Exporting Go to Structure > Structure sync. You will see Taxonomies, Custom blocks and Menu links tabs. Choose one that you want to export. Select the item/items you want to export and click the Export button. You should see a success message that tells that you have successfully exported the items. Go to Configuration > Configuration synchronization > Export to get the configuration sync file. This file will include the structure sync export files.   Importing Go to Configuration > Configuration synchronization > Import and upload the configuration sync file. (You can skip this step if your configuration sync file is committed on your repo and you have your sync folder fully configured) Go to Configuration > Configuration synchronization > Synchronize and click the Import all button to import everything from the config sync file. After the sync is finished, go to Structure > Structure sync. You will see Taxonomies, Custom blocks and Menu links tabs. Choose one that you want to import. Click Import button accordingly.