Skip to main content

Blog

Agaric Sponsors Modulecraft for the Building of Drupal Shared business, Development, and Training Tools

For community shared business, development, and training tools, Agaric throws a little sponsorship at modulecraft.

Agaric Provides Very Minor Assist in Readying Insert Module for Drupal 7

Benjamin Melançon of Agaric helped with a patch for the Drupal 7 version of Insert module.

A round red capped mushroom with white spots.

Agaric?

What the word agaric means and why Agaric took it for our cooperative's name.

Designed to Life

Functionality designed to your life is the Agaric Design signature. Utilizing open source, free software from around the world, Agaric Design websites are impeccably crafted with a modern, sophisticated and understated spirit.

The Story on Agaric

I've always had a passion for good design and healthy coding, even back in the days of owning a web site cart in downtown Natick. Back then, my business partner and I made all natural HTML roll-up web sites and, as an incentive for customers to wait in line, we baked Drupal into different flavored designs.

Full participation in Agaric's Drupal 8 migrations quickstart (half-day training) and Drupal 8 content migrations (full-day training) courses requires a working, local installation of Drupal 8.

The morning can be done online with a Pantheon.io free development site or SimplyTest.me (only web browser and working internet connection required).

Development Environment

The afternoon portion of the training requires a local dev environment— if you aren't able to get this set up ahead of time, we can help you during a break.  The two approaches we have tested:

All of these approaches work on GNU/Linux, MacOS, and Windows.

Prerequisites

Although no prior Migrate module knowledge is required, it is expected that you have a basic understanding of nodes, content types, and fields. You can learn about these and other Drupal concepts by watching this session recording.

A working Drupal 8 installation is required. It is possible to follow some examples using a hosted Drupal service like pantheon.io To get the most out of the training a local installation is needed. Installing Drupal locally using composer is recommended.

Drush needs to be installed in order to run migrations from the command line. Xdebug and PHPStorm are used for the debugging example (techniques apply for other debuggers and IDEs).

It is recommended to use DrupalVM and configure it to use the drupal composer template.

Follow the quickstart guide to install DrupalVM with the xdebug extra package.

Install the following contrib modules:

  • address
  • entity_reference_revisions
  • migrate_plus
  • migrate_source_csv
  • migrate_tools
  • paragraphs

Assistance can be provided before the training starts, but it is better to come with your local environment already set up.

About the trainers:

Agaric builds websites and online platforms that give people more control over their technology, including working with Drupal for more than thirteen years. They bring their expertise in backend development and Drupal migrations to projects for clients in different sectors including government, education, businesses, and not-for-profits/NGOs. Agaric is committed to giving back to the community. Over the last few years, they have presented 40+ sessions and full day trainings in 16+ DrupalCamps and DrupalCons in the Americas and Europe.

Benjamin Melançon (mlncn on drupal.org) has been working with Drupal since 2005.  He led the 36 author project that produced the Definitive Guide to Drupal 7 and contributed dozens of modules to Drupal 5, 6, 7, and 8.  For client projects, Benjamin uses this deep understanding of Drupal internals along with more general frontend, backend, and infrastructure knowledge to make sure requirements and expectations are met. He is a frequent speaker at Drupal and other technology events in North America.

Mauricio Dinarte is passionate about teaching. He is creating educational material in English, Spanish, and French to help break the language barrier when learning Drupal and other technologies. Check out his educational project at https://understanddrupal.com.

Conclusion

With the In Other Words module, it is now possible to keep your structured content and display it naturally. The logic of how a list should display in various scenarios is boiled down to an intuitive user interface for site builders, with no coding required. Try it for yourself! Get the module at drupal.org/project/inotherwords.

The Challenge

Increasingly, the entities and individuals who participate in such initiatives are geographically dispersed with limited opportunities for in-person or contemporaneous collaboration. They need spaces where they can work asynchronously—online communities that enable teams to share ideas and best practices, receive feedback from experts, and exchange resources. And each space or community needs to be their own. The required feature set is robust, but common—the perfect fit for a Drupal distribution. The NICHQ Collaboratory (“CoLab”) provided such spaces, but they were powered by a Drupal 7 distribution which made site-specific customization and ongoing maintenance fraught and unmanageable. Moreover, the list of improvements slated for implementation was increasing, and there was growing consensus that the information architecture for resources and other information needed rethinking.

Our Approach

Research-Driven Information Architecture

Anecdotally, we knew the sites could use an upgrade, but there were also features users appreciated. In our upgrade, we did not want to disrupt any beloved processes in our quest for improving the experience.

We started with a survey to find the common pain points and the loved features to leave intact. We learned that overall people still loved the visual design, felt the quality of content was high, and moderation was strong. Most respondents were overwhelmed with the amount of content, despite its quality, and didn't find the notification system helpful.

The next step was to dig deeper to learn why exactly content was hard to find and the best way to solve this. The survey asked if the respondent would be interested in a follow-up interview so we had a good list to draw from.

We knew from our prior audience work that there were two primary user groups: Project Managers and Participants. We decided to start by interviewing one project manager, a new participant and a veteran participant. After this first round of interviews we would then decide if more research was needed.

There were some surprising findings. One is that each community had groups within it, for more specific topics. However, none of the interviewees used these groups. In fact, they got in the way of collaboration. For them, collaboration meant transcending groups and working with anyone within the team. We also learned that categorization had run a bit wild. Different users were tagging resources in different ways and there were terms that served the same purpose, creating redundancy and inconsistent tagging. This was both a process challenge and a technical one. NICHQ would get on the same page about how to categorize content and we would lock down the ability to add new categories, only to project managers.

Atomic Wireframes

We do not build websites page by page, but rather in components that get reused across a site. Atomic design is a way to conceive of components made up of smaller components, made up of even smaller components.

To ease development and design, we built our wireframes using the same concept. In Sketch these are called symbols.

Wireframe to Design is Not Clean

It is tempting to punt all design questions until after wireframes are approved. However, sometimes it is too difficult for us to envision the functionality of something without more design polish added to it.

So, instead of pure, clean transitions we moved from wireframes to design knowing that some questions were still unresolved.

Luckily, our "atomic wireframes" were easy for our designer Todd Linkner to update.

Screenshot of the NICHQ Colab feed.
The CoLab Feed is where collaborators stay informed of upcoming events and see the latest member activity.

Advancing the Power of Distributions to Drupal 8

As mentioned above, NICHQ's need for multiple sites using similar feature sets was the perfect fit for a Drupal distribution. However, we needed a workflow that could allow some sites to diverge from the original codebase but still bring in future improvements.

We had already started in on this endeavor with Drutopia, an initiative to improve the way Drupal manages configuration and distributions.

With the NICHQ CoLab as our practical use case, we worked with the Drupal shop Chocolate Lily to build and improve upon a suite of modules to manage and share different states of configuration across distributions.

For more, read this excellent series of posts by Nedjo Rogers.

Screenshot of a user asking their NICHQ Colab  community a question.
Users can ask the community a question they have about children's health.

Training FAQ

Here are some quick answers to Frequently Asked Questions about Agaric trainings.

Can I get a discount when purchasing more than one training?

Yes, a 15% discount is available for additional trainings. Contact Agaric after purchasing your first training to get the information needed to purchase second or third at a discount.

Are scholarships available?

Yes, partial and full scholarships are available! We are prioritizing people facing disadvantages, in particular survivors of historical and ongoing discrimination and people under-represented in technology. Contact Agaric with your circumstances and for more information. Agaric will review your submission internally only— we do not share the information you provide in determining your eligibility for a discount/scholarship with anyone outside Agaric.

What if my corporate employer cannot submit payment for my attendance before the training date? If your company sees the benefit of you getting training from Agaric but the accounts payable department will not be able to accommodate fulfilling payment prior to the training date, please contact us for an invoice due up to 90 days after the training. I'm not sure I meet the prerequsites or will be able to set up a development environment.

Every training includes sessions ahead of time to help everybody get their local development environment set up before the training (if needed). We'll also direct you to other resources helpful for getting up to speed before the training. Contact Agaric to check in with where you are to get our help ensuring you get the full benefit of the training.

Can I cancel and get a refund?

No, we do not offer refunds but tickets are transferable and we'll help you re-sell the ticket, so please contact Agaric if you can't make the training.

Will I receive a recording or other materials?

Yes, all attendees will be sent recordings from the training as well as the curriculum and materials used in the training and additional books or other references and resources.

Will Agaric provide a certificate of completion?

Yes, all students who participate in the full training will receive a Certificate of Completion.

 
Have more questions? Ask Agaric!

Agaric adapts our approach to fit each project. Some building blocks to our approach are so fundamental that we use them on nearly every Drupal project we work on. These are those fundamental aspects to our approach.

Results-Driven Design

Design can be a nebulous, subjective process. We give that process structure and purpose by focusing on the results. The design system we create speaks to your audience and meets your goals. We share our designs early, with real content, and in as interactive of a way as possible with your key stakeholders.

Knowing that design is never truly done, we like to get the design "80% of the way there", and then apply it to the actual site. That way we can improve and refine along the way using the actual site, not static files open to misinterpretation.

By launch time your site will have a design that is:

  • On-brand - speaks to your audience
  • Results-driven - prioritizes the right content in the right contexts
  • Secure - built on a theme covered by the Drupal security team and implementing security best practices
  • Accessible - works with assistive devices and keyboard-only navigation
  • Responsive - looks beautiful on any device
  • Extensible - well organized templates to easily adjust or add new design components as your site evolves.

Digital Commons Development

Drupal is a free software project built by thousands of designers and developers. As a result, your site benefits from security coverage and high quality code that follows best practices and ongoing maintenance and improvement.

As leaders in the Drupal community, we contribute to Drupal Core and maintain dozens of public modules (called "contributed modules" in the Drupalsphere) used by thousands of sites. For nonprofits in particular we are helping to build a Drupal 8 distribution putting together and providing ready-to-go configuration for key modules, many of which we also contribute to.

We draw from shared solutions whenever possible, tapping into and contributing back to this digital commons, because it saves time by not reinventing the wheel, and ensures your site continues to be maintainable and benefits from ongoing improvements from the community.

Accessibility

It is critical that your site be accessible to as many people as possible, including those using screen readers. To that end, all of our work is built to support compliance with W3C Web Content Accessibility Guidelines (WCAG) 2.0. The WCAG Guidelines, however, are not comprehensive and so we go beyond those guidelines to ensure high accessibility. Lastly, much of what makes a site accessible happens on the content entry and management side. We will provide resources for your content team so that after the site launches, you can rest assured that what you are creating is reaching as many people as possible.

Search Engine Optimization

Our developers will also follow SEO best-practice development and utilize Drupal’s range of SEO-related features that allow administrators to edit page titles, implement human-readable and editable URLs, enter meta tag information, and more. For further SEO-related services, we can also recommend SEO consultants.

Ksnip screenshot tool.

 

 

I recently switched from Mac OS to Elementary, a Linux distribution focused on ease of use and privacy. As both a user experience designer and free software supporter, I am taking screenshots and annotating them all the time. After trying out several different tools, the one I enjoy by far is Ksnip.

Installation

Install ksnip with your preferred package manager. In my case I installed it via apt

sudo apt-get install ksnip

Configuration

Ksnip comes with quite a few configuration options, including:

  • Location to save screenshots to
  • Default screenshot file name
  • Image grabber behavior
  • Cursor color and thickness
  • Text font

You can also integrate it with your Imgur account.

Configuration settings of Ksnip.

Usage

My favorite part of Ksnip is that it has all the annotation tools I need (plus one I hadn't thought of!).

You can annotate with:

  • pen
  • marker
  • rectangles
  • ellipses
  • text

You can also blur areas to remove sensitive information.

And my new favorite tool, numbered dots for steps on an interface.

KSnip Features List - https://github.com/DamirPorobic/ksnip#features

About the Creator

I'm enjoying Ksnip so much that I reached out to the creator, Damir Porobic, to learn more about the project.

I asked what inspired him to create Ksnip and here's what he said,

"I switched from Windows to Linux a few years ago and missed the Windows Snipping Tool that I was used to on Windows. All other screenshot tools at that time were either huge (a lot of buttons and complex features) or lacked key features like annotations so I decided to build a simple Snipping Tool Clone but with time it got more and more feature so here we are."

This is exactly what I found as I was evaluating screenshot tools. It's great that he took the time to build a solution himself and freely share it for others to benefit from.

As for the future of Ksnip, Damir would like to add Global Shortcuts (at least for Windows), tabs for new screenshots, and allow the application to run in the background. There is also a growing list of feature requests on GitHub.  

Ways to Help

The biggest need is with development. Damir and his wife are expecting a baby soon so he won't have as much time to devote to the project. He is available to review and accept pull requests though.

Also, the project could benefit from additional installation options via Snap, Flatpak and installers for MacOS and a Setup for Windows.

Lastly, use the project, rate it and review it on AlternativeTo.net and other tech comparison platforms and if you can spare a few bucks, donations are always appreciated.

 

We are a worker-owned cooperative specializing in building tools and websites that respect your freedom. We also provide training and consultation to meet your goals. Everything we do is part of our purpose to help all people gain the most power possible over their own lives.

In the previous article we provided a reference of available configuration options for migrate source plugins. In today’s article we are doing something similar for destination plugins. We will present a reference of available configuration options for migrate destination plugins provided by Drupal core and some contributed modules. Knowing which options are available might require some Drupal development knowledge. By providing this reference it should make the process of writing migrations easier.

List of configuration options for destination plugins

For each migrate destination plugin we will present: the module that provides it, the class that defines it, the class that the plugin extends, and any inherited options from the class hierarchy. For each plugin configuration option we will list its name, type, a description, and a note if it is optional.

DestinationBase (abstract class)

Module: Migrate (Drupal Core)
Class: Drupal\migrate\Plugin\migrate\destination\DestinationBase
Extends: Drupal\Core\Plugin\PluginBase

This abstract class is extended by many migrate destination plugins. This means that the provided configuration keys apply to any destination plugin extending it.

List of configuration keys:

  1. destination_module: An optional string value. Identifies the module handling the destination data. If not set, the Migrate API tries to read the value from the destination plugin definition.

Entity (abstract class)

Module: Migrate (Drupal Core) Plugin ID: entity:$entity_type See below.
Class: Drupal\migrate\Plugin\migrate\destination\Entity
Extends: Drupal\migrate\Plugin\migrate\destination\DestinationBase
Inherited configuration options: destination_module.
Related article: Drupal migrations reference: List of properties per content entity

This abstract class is extended by migrate destination plugins that want to import entities. It uses the MigrateEntity derivative to handle both content and configuration entities. The derivative sets the plugin ID to entity:$entity_type where $entity_type is the machine name of the entity. For example, entity:node and entity:node_type.

By default, content entities are handled by the EntityContentBase class while configuration entities use EntityConfigBase. Some entities like user (content) and node type (configuration) use specific classes for the import operation. The DefaultPluginManager::getDefinitions method triggers the search for classes that will override the default for a particular plugin ID. The override ultimately happens in the DerivativeDiscoveryDecorator::getDerivatives method.

In addition to the keys provided in the parent class chain, this abstract class provides the following configuration keys, which will be available to its derivatives:

  1. default_bundle: An optional string value. Gets the bundle for the row taking into account the default. If not present, the bundle entity key should be set in the process section for entities that can have more than one bundle. For example, the type property for nodes, the vid property for taxonomy terms, and the bundle property for media entities.

EntityContentBase

Module: Migrate (Drupal Core) Plugin ID: entity:$entity_type See below.
Class: Drupal\migrate\Plugin\migrate\destination\EntityContentBase
Extends: Drupal\migrate\Plugin\migrate\destination\Entity
Inherited configuration options: destination_module and default_bundle.

This class is used to handle import operations for all content entities, unless a specific class exists for the plugin ID being used. For example, nodes are handled by this class, but users leverage the EntityUser class. The MigrateEntity derivative sets the plugin ID to entity:$entity_type where $entity_type is the machine name of the content entity. For example, entity:node, entity:user, entity:taxonomy_term, entity:file, entity:media, entity:comment, entity:block_content, and entity:contact_message.

In addition to the keys provided in the parent class chain, this class provides the following configuration keys:

  1. translations: An optional boolean value. It indicates if the entity is translatable, defaults to FALSE. If set to TRUE, the corresponding langcode entity key will be added to the list of destination IDs that uniquely identifies each record. If the migration itself does not provide a value for the langcode property, the site’s default language is used.
  2. overwrite_properties: An optional array of string values. It is a list of properties or fields in the destination entity that will be overwritten if an entity with the same ID already exists. Any properties that are not listed will not be overwritten. Refer to the class documentation for an example.
  3. validate: An optional boolean value. It indicates whether an entity should be validated, defaults to FALSE. This was introduced in Drupal 8.8 and can be used to prevent invalid entities from being migrated. For example, a node with an empty title would fail validation. A required field that is not set by the migration will trigger a validation error, unless the field is configured to have a default value. Similarly, an integer field with minimum and maximum values will trigger an error if a value outside that range tries to be imported. Field API validations are triggered when this configuration option is set to TRUE.

EntityUser

Module: User (Drupal Core) Plugin ID: entity:user See below.
Class: Drupal\user\Plugin\migrate\destination\EntityUser
Extends: Drupal\migrate\Plugin\migrate\destination\EntityContentBase
Inherited configuration options: destination_module, default_bundle, translations, overwrite_properties, and validate.

This class provides a destination plugin for migrating user entities. It performs extra checks like preventing that the password for user 1 is overridden by the migration.

In addition to the keys provided in the parent class chain, this abstract class provides the following configuration keys:

  1. md5_passwords: An optional boolean value. If set to TRUE, the pass (password) property of the user entity is assumed to contain an MD5 hash. The passwords will be salted and re-hashed before they are saved to the destination Drupal database.

EntityRevision

Module: Migrate (Drupal Core) Plugin ID: entity_revision:$entity_type See below.
Class: Drupal\migrate\Plugin\migrate\destination\EntityRevision
Extends: Drupal\migrate\Plugin\migrate\destination\EntityContentBase
Inherited configuration options: destination_module, default_bundle, translations, overwrite_properties, and validate.

This class provides an entity revision destination plugin. Only revisionable entities, those that define a revision entity key, can use this destination plugin. It uses the MigrateEntityRevision derivative which sets the plugin ID to entity_revision:$entity_type where $entity_type is the machine name of the entity. For example, entity_revision:node whose revision key is vid and entity_revision:block_content whose revision key is revision_id.

Entity revisions can only be migrated after the entity to which they belong has been migrated. For example, revisions of a given node (entity_revision:node destination migration) can be migrated only after the current version of that node (entity:node destination migration) has been imported.

EntityReferenceRevisions

Module: Entity Reference Revisions module Plugin ID: entity_reference_revisions:$entity_type See below.
Class: Drupal\entity_reference_revisions\Plugin\migrate\destination\EntityReferenceRevisions
Extends: Drupal\migrate\Plugin\migrate\destination\EntityRevision
Inherited configuration options: destination_module, default_bundle, translations, overwrite_properties, and validate.
Related article: Introduction to paragraphs migrations in Drupal

This class provides an entity revision revision destination plugin. It uses the MigrateEntityReferenceRevisions derivative which sets the plugin ID to entity_reference_revisions:$entity_type where $entity_type is the machine name of the entity. For example, entity_reference_revisions:node and entity_reference_revisions:paragraph. For example, entity_reference_revisions:node whose revision key is vid and entity_reference_revisions:paragraph whose revision key is revision_id.

This is the destination plugin used for migrating Paragraphs. Entity reference fields are no longer supported to reference Paragraphs. Instead, entity entity reference revisions must be used. Therefore, this class is used for paragraphs migrations with the entity_reference_revisions:paragraph plugin ID. See this article for an example on how to migrate paragraphs.

In addition to the keys provided in the parent class chain, this abstract class provides the following configuration keys:

  1. new_revisions: An optional boolean value. Flag to indicate if a new revision should be created instead of updating a previous default record. Only applicable when providing an entity id without a revision_id. Defaults to FALSE.

EntityConfigBase

Module: Migrate (Drupal Core) Plugin ID: entity:$entity_id See below.
Class: Drupal\migrate\Plugin\migrate\destination\EntityConfigBase
Extends: Drupal\migrate\Plugin\migrate\destination\Entity
Inherited configuration options: destination_module and default_bundle.

This class is used to handle import operations for all configuration entities, unless a specific class exists for the plugin ID being used. For example, taxonomy vocabularies are handled by this class, but node types leverage the EntityNodeType class. The MigrateEntity derivative sets the plugin ID to entity:$entity_type where $entity_type is the machine name of the content entity. For example, entity:node_type, entity:user_role, entity:taxonomy_vocabulary, entity:block, entity:comment_type, entity:block_content_type, entity:contact_form, entity:date_format.

In addition to the keys provided in the parent class chain, this abstract class provides the following configuration keys:

  1. translations: An optional boolean value. if TRUE, the destination will be associated with the langcode provided by the source plugin. Defaults to FALSE. For example: en for English, es for Spanish, and fr for French.

EntityNodeType

Module: Node (Drupal Core) Plugin ID: entity:node_type
Class: Drupal\node\Plugin\migrate\destination\EntityNodeType
Extends: Drupal\migrate\Plugin\migrate\destination\EntityConfigBase
Inherited configuration options: destination_module, default_bundle, and translations.

This class is used to import node types. It does not take extra configuration options. The plugin overrides the import method to attach the body field to the imported content type. This depends on the presence of certain destination properties in the imported row. That is, the following properties needs to be mapped in the process section of the migration:

  1. create_body: An optional boolean value. If TRUE, a body field will be added to the content type.
  2. create_body_label: An optional string value. If set and create_body is TRUE, the value for this destination property will be used as the label of the body field.

Config

Module: Migrate (Drupal Core) Plugin ID: config
Class: Drupal\migrate\Plugin\migrate\destination\Config
Extends: Drupal\migrate\Plugin\migrate\destination\DestinationBase
Inherited configuration options: destination_module.

This class persists data to the configuration management system. In addition to the keys provided in the parent class chain, this class provides the following configuration keys:

  1. store null: An optional boolean value. If TRUE, when a property is NULL, the NULL value is stored. Otherwise, the default value is used. Defaults to FALSE. Note that there is a space character in the configuration name.
  2. translations: An optional boolean value. if TRUE, the destination will be associated with the langcode provided by the source plugin. Defaults to FALSE.

Additionally, the plugin expects certain destination properties in the imported row. That is, the following properties needs to be mapped in the process section of the migration:

  1. config_name: A string value. The machine name of the configuration. For example: node.settings, node.type.article, user.settings, system.site, and core.extension.
  2. langcode: An optional string value. The language code of the configuration. For example: en for English, es for Spanish, and fr for French.

Table

Module: Migrate Plus Plugin ID: table
Class: Drupal\migrate_plus\Plugin\migrate\destination\Table
Extends: Drupal\migrate\Plugin\migrate\destination\DestinationBase
Inherited configuration options: destination_module.

This class allows you to write directly to a table not registered with Drupal Schema API. See this test for an example on how to use this plugin.

In addition to the keys provided in the parent class chain, this class provides the following configuration keys:

  1. database_key: An string value. Key for the database connection used for inserting records. See this documentation page for more information on database connection keys. We also covered the topic when explaining the SqlBase source plugin.
  2. table_name: An string value. Name of the table where records will be imported.
  3. batch_size: An optional integer value. Maximum number of rows to insert in one query. Defaults to 1.
  4. id_fields: An associative array value. Fields used to uniquely identify table rows. At least one field is required. See the class’s docblock for an example of the expected structure.
  5. fields: An optional associative array value. Mapping of column names to values set in the process section.

Available configuration for other migrate destination plugins

In Drupal core itself there are around 50 migrate destination plugins. And many more are made available by contributed modules. It would be impractical to document them all here. To get a list by yourself, load the plugin.manager.migrate.destination service and call its getDefinitions() method. This will return all migrate destination plugins provided by the modules that are currently enabled on the site. This Drush command would get the list:

# List of migrate destination plugin definitions. $ drush php:eval "print_r(\Drupal::service('plugin.manager.migrate.destination')->getDefinitions());" # List of migrate destination plugin ids. $ drush php:eval "print_r(array_keys(\Drupal::service('plugin.manager.migrate.destination')->getDefinitions()));"

To find out which configuration options are available for any destination plugin consider the following:

  • Find the class that defines the plugin and find out which configuration values are read. Some plugins even include the list in the docblock of the class. Search for a pattern similar to $this->configuration['option_name'] or $configuration['option_name']. The plugins can be found in the Drupal\module_name\Plugin\migrate\destination namespace. The class itself would be in a file under the /src/Plugin/migrate/destination/ directory of the module.
  • Look up in the class hierarchy. The destination plugin can use any configuration set directly in its definition class and any parent class. There might be multiple layers of inheritance.
  • Check if the plugin requires the presence of specific destination properties to be set in the process section. This is usually documented in the class’ docblock, but you can also look for code like $row->getDestinationProperty('property_name').

What did you learn in today’s article? Did you know that migrate destination plugins can inherit configuration keys from their class hierarchy? Were you aware that there are so many destination plugins? Other than the ones listed here, which destination plugins have you used? Please share your answers in the comments. Also, we would be grateful if you shared this article with your friends and colleagues.

E-mail us at ask@agaric.coop, call us at +1 508 283 3557, or use this form below, and one of us worker-owners at Agaric will get back to you.

Oh yeah!

I'm back! Because I knew this blog post wasn't quite long enough already...certainly not because it occurred to me that I left off another alternative I've used in a pinch.

The one-off

If you want to run a command using a different version of php, rather than rely on the shebang, you can always just call the desired script as an argument to php itself. When you run, e.g. drush status, your shell sees the #! on the first line, and uses that as the default interpreter for the script. In essence, your command is translated into /usr/bin/env php drush status.

Rather than accept this default, you can specify the specific version on your command line, such as php8.1 drush status. In this case the #! is just ignored. Unfortunately, this method can only get you so far - particularly with drush. Drush often figures out what your command requires and in turn will spawn other php scripts to do the dirty work. These spawned scripts are unaware of the interpreter that drush itself was started with.