This is the Drupal 8 version of https://www.ilr.cornell.edu, AKA The Marketing Site.
It is based on the Composer template for Drupal projects.
- git
- PHP 7.2 or greater
- the PHP ImageMagick extension (for PDF thumbnail generation)
- Composer
- Drush (Drush launcher is recommended, since a copy of Drush is included in this project)
- Node.js 8.x or greater (for theming)
- Clone this repository
- Open a terminal at the root of the repo
- Run
composer install
- Copy
.env.example
to.env
and update the database connection and other info. - Run
npm install && npm run build
to generate the CSS for the custom theme.
Setting up your local web server and database is left as an excercise for the developer. Please note when setting up your web server, though, that this project uses the web
directory as the web root.
You may wish to configure some settings (cache, config splits, etc.) for local development. To do so, you may optionally add a settings.local.php
file to web/sites/default/
.
Here's a suggested example:
<?php
// Allow any domain to access the site.
$settings['trusted_host_patterns'] = [];
// Switch the salesforce auth provider to production if needed.
// Otherwise, we will use the default for dev.
// $config['salesforce.settings']['salesforce_auth_provider'] = 'ilr_marketing_jwt_oauth';
// Enable the config split for development-only modules, like field_ui.
$config['config_split.config_split.dev']['status'] = TRUE;
// Enable local development services.
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/local_development.services.yml';
// Show all error messages, with backtrace information.
$config['system.logging']['error_level'] = 'verbose';
// Show more cron logging info, including in `drush cron`.
$config['system.cron']['logging'] = TRUE;
// Disable CSS and JS aggregation.
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;
// Skip file system permissions hardening.
$settings['skip_permissions_hardening'] = TRUE;
// Allow local access to media entity canonical URLs (e.g. /media/1).
$config['media.settings']['standalone_url'] = TRUE;
To work on a blank slate of the codebase without syncing content and data from production, install Drupal like so:
$ drush si minimal --existing-config
Use standard composer commands to add, remove, and update project dependencies. To add the rules module, for example, run:
$ composer require drupal/rules:~1.0
To add a module for developer use only, which will prevent its installation on the production site, use the --dev
paramater, like so:
$ composer require --dev drupal/devel:~1.0
Outdated Drupal modules can be listed with the following command:
$ composer outdated "drupal/*"
To update a specific module, run something like:
composer update drupal/rules
If you need to apply patches (depending on the project being modified, a pull request is often a better solution), you can do so with the composer-patches plugin.
To add a patch to drupal module foobar insert the patches section in the extra section of composer.json:
"extra": {
"patches": {
"drupal/foobar": {
"Patch description": "URL or local path to patch"
}
}
}
$ composer update drupal/core 'drupal/core-*' --with-all-dependencies
Then run git diff
to determine if any of the scaffolding files have changed.
Review changes and restore any customizations to .htaccess
or robots.txt
. Commit everything together in a single commit (or merge), so web
will remain in sync with core
when checking out branches or running git bisect
.
See https://www.drupal.org/node/2700999 for more information.
As with many Drupal 8 sites, configuration is managed in version control by exporting it to the filesystem. This project is configured, via $settings['config_sync_directory']
in settings.php
, to store configuration in the ./config/sync/
directory.
During development, configuration is exported via drush cex
. For example, if a new content type were created on a local development site, the node type and field config would be exported, and the new config yml files would be committed to git.
During deployment, modified configuration is synchronized via a script that runs drush cim
on the production site. In general, this means that any configuration added or modified on production will be reverted or removed during deployment. For example, if a new content type were added on production, it would be remove during deployment.
While most configuration is created during local development and then deployed to production, some configuration is generated automatically directly on the production site.
Some examples:
- The
collection_subsites
module generates a menu and a block visibility group when a new subsite collection is created. - The
collection_blogs
module generates category and tag taxonomy vocabularies when new blog collections are created.
Since new subsites and blogs can be created by administrators on the production site, we don't want those menus, block visibility groups, and vocabularies accidentally deleted during a deployment.
Additionally, we don't want this generated configuration exported to the config/sync/
directory during local development.
Therefore, some configuration is ignored using import and export config storage transform events: config.transform.export
and config.transform.import
. See the configuration transform event change record for more information.
The event subscribers can be found in \Drupal\ilr\EventSubscriber\ConfigEventSubscriber
. The ignore patterns are, for now, manually maintained in that file in the $ignoredPatterns
property.
On occasion, ignored configuration needs to be updated via deployment. For example, the display view mode for a blog category taxonomy page may be need to be updated.
For these cases, the transform event subscribers in ConfigEventSubscriber
check for ignored configuration items in config/sync/
and don't ignore them if they are found.
Continuing the view mode example above, imagine that a developer updates the default view display for a blog category taxonomy vocabulary with the machine name blog_2_categories
. This vocabulary display view mode was generated on production when the collection blog with the id 2
was created.
Assuming that the developer is very clever and knows the exact name of the configuration item for that view mode, it can be exported, bypassing the ignore filters, with two commands:
$ touch config/sync/core.entity_view_display.taxonomy_term.blog_2_categories.default.yml
$ drush cex
You can get a bit of help finding the names of configuration items by using the single item export utility at /admin/config/development/configuration/single/export
.
This site uses the Salesforce Suite module to synchronize some Salesforce objects to Drupal entities, mainly Professionional Programs courses, classes, and related items.
Authentication is done via OAuth JWT tokens - one for ILR Drupal sites to connect to the production instance and one for all development sites to connect to the tiger
sandbox instance. See the OAuth JWT Bearer Token flow documentation for more information.
The only required configuration is to set the SALESFORCE_CONSUMER_JWT_X509_KEY
environment variable. For development, this is done by editing the .env
file. On production, this is done via platform.sh environment variable settings.
The JWT x509 key is stored in the 'SalesForce prod key/secret for ILR Marketing D8 JWT' note in the shared 'ILR Webdev' folder in LastPass.
You can see the status of the two authentication providers via drush:
$ drush sflp
...or by visiting /admin/config/salesforce/authorize/list
.
You can then refresh the authentication tokens for one or both of the providers by either using the Edit / Re-auth button in the web interface or via drush:
$ drush sfrt ilr_marketing_jwt_oauth_dev
If needed, the default provider can be overriden during local development (e.g. for testing with production data) by updating the configuration for the salesforce_auth_provider
. See the "Development-only Settings" above for an example.
Several migrations are defined in config/migrations/migrate_plus.migration.*.yml
.
Most of these migrations require a drupal7
database 'Connection key', which should define a connection to the Drupal 7 database.
For local development and testing, the connection key can be configured via the .env
file. See .env.example
for more information on populating the MYSQL_MIGRATE_*
environment variables.
In addition to the migration configurations, some custom migrate code, including source plugins, can be found in the custom ilr_migrate
module.
$ drush ms --group=drupal_7
All Drupal 7 content can be migrated via:
$ drush mim --group=drupal_7
Individual migrations can be run like so:
$ drush mim d7_node_course
Some migrations can take a long time to run. For those migrations, you can configure the --feedback
parameter so you can see some progress. For example:
$ drush mim d7_file_media --feedback="500 items"
The d7_file_media
migration can run especially long, since it must download media items from the production D7 site via http. During development, you can speed this migration by copying the D7 site files to your local machine and overriding the source to use these local files.
There are two things you must do to enable local files as the source of the media migration.
From the D7 codebase:
rsync -azv --progress --iconv=utf-8-mac,utf-8 `platform ssh --pipe`:/app/web/sites/default/files/ /Users/YOUR_USERNAME/ILR/d7_files/sites/default/files/
Ensure that you are using rsync
3.x or above.
Enable and update the MIGRATE_MEDIA_SOURCE_BASE_PATH_OVERRIDE
environment variable in .env
to point to the local file source (e.g. the rsync
destination from the above command). See .env.example
for more info.
Note that the migration source will be looking for files relative to the Drupal root, so if your local files are in /Users/YOUR_USERNAME/work/ilr/d7_files/sites/default/files
, you'll set MIGRATE_MEDIA_SOURCE_BASE_PATH_OVERRIDE
to /Users/YOUR_USERNAME/work/ilr/d7_files
.
The d7_file_media
migration transforms the D7 site files (including images) into D8 media entities. Initially, the D7 file id (fid
) was mapped to the D7 media id (mid
), so that for any given file entity in D7, there is a corresponding media entity in D8 with the same id.
As of Jan 2021, the media migration has been updated to create new mid
values for imported media. This allows the migration to be run again when new D7 media is added, but now requires a migration lookup in other migrations.
This project uses a custom theme that includes shared components from the Union Component Library.
The custom theme is found in web/themes/custom/union_marketing/
. The Sass CSS preprocessor is used for styles, and you can compile CSS either 1) manually via npm run build
or 2) automatically by running npm start
in a spare terminal.
Union Components are integrated into the theme using the Union Organizer module. See the documentation for that module for more information.
If you set LIVERELOAD=1
in your .env
file and reload your browser while npm start
is running, changes to stylesheets will reload automatically in your browser.