Date post: | 08-May-2015 |
Category: |
Technology |
Upload: | swentel |
View: | 4,062 times |
Download: | 0 times |
Drupal 8 Configuration system for coders and site builders
Friday 23 August 13
who am I?
Kristof De Jaeger@swentel
Co-maintainer of Field APILead maintainer of Display Suite
Developer @ Wunderkraut
Friday 23 August 13
Outline• What’s the problem
• How did we solve it
• Simple static settings
• Configuration entities
• Deployment - with demo
• Configuration schema
• Context, events and overrides
Friday 23 August 13
What problems are we trying to solve?
• Variable soup
Live
Save
textSetting 1Setting 2 label
Database Database
Dev
TESTtest test test test test test test test test test test test test test
node/4admin/config/foo
WelcomeThis is real content on the live site that end users are viewing
node/4
Save
old textSetting 1Setting 2 label
admin/config/foo
Friday 23 August 13
Live
Save
textSetting 1Setting 2 label
Database Database
Dev
TESTtest test test test test test test test test test test test test test
node/4admin/config/foo
WelcomeThis is real content on the live site that end users are viewing
node/4
Save
old textSetting 1Setting 2 label
admin/config/foo
Danger!Want to bring over configuration
changes from dev, but not overwrite live content!
What problems are we trying to solve?
Friday 23 August 13
What problems are we trying to solve?
variable_set()/variable_get()
ctools_export_object()/ctools_export_load_object()
db_select()/db_update()/db_delete()
$conf[...];hook_update_N()
drush fu
http://www.flickr.com/photos/bean/322616749
napkins
Friday 23 August 13
The solution
• Files using the YAML specification
• Active and staging directory
• Cached in the database using a standard cache interface
• Config directory changed via settings.php
Friday 23 August 13
The anatomy of a configuration file
Friday 23 August 13
system.site.yml
Friday 23 August 13
system.site.yml
Friday 23 August 13
system.site.yml
Friday 23 August 13
name: 'Configuration management'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: '' 404: '' front: node
system.site.yml
Friday 23 August 13
The API
Drupal::config()
->get()
->set()
->save()
Friday 23 August 13
Accessing data
Friday 23 August 13
name: 'Configuration management'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: '' 404: '' front: node
$site_name = Drupal::config('system.site')->get('name');
Friday 23 August 13
$page_data = Drupal::config('system.site')->get('page');
name: 'Configuration management'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: '' 404: '' front: node
Friday 23 August 13
$frontpage = Drupal::config('system.site')->get('page.front');
name: 'Configuration management'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: '' 404: '' front: node
Friday 23 August 13
$all_the_data = Drupal::config('system.site')->get();
name: 'Configuration management'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: '' 404: '' front: node
Friday 23 August 13
Saving data
Friday 23 August 13
name: 'CMI is good'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: '' 404: '' front: node
Drupal::config('system.site') ->set('name', 'CMI is good') ->save();
Friday 23 August 13
name: 'CMI is great'mail: [email protected]: 'makes Drupal 8 cex -y'page: 403: access-denied 404: not-found front: user
Drupal::config('system.site') ->set('name', 'CMI is great') ->set('page', array( 403 => 'access-denied', 404 => 'not-found', front => 'user', )) ->save();
Friday 23 August 13
Friday 23 August 13
• system_settings_form is dead
• add your own submit callback
• you are responsible for saving configuration
• ship with default configuration file
simple settings
Friday 23 August 13
{system}
{date_format_locale}
{date_formats}
{date_format_type}
{field_config}
{field_config_instance}
{filter}
{filter_format}
{node_type} {role}{role_permission}
{variable}
{language}
Friday 23 August 13
Config all the things!
Friday 23 August 13
Config entities
Friday 23 August 13
<?php
/** * @file * Definition of Drupal\contact\Plugin\Core\Entity\Category. */
namespace Drupal\contact\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;use Drupal\Core\Annotation\Plugin;use Drupal\Core\Annotation\Translation;
/** * Defines the contact category entity. * * @EntityType( * id = "contact_category", * label = @Translation("Category"), * module = "contact", * controllers = { * controller_class = "Drupal\contact\CategoryStorageController", * list = "Drupal\contact\CategoryListController", * form = { * "add" = "Drupal\contact\CategoryFormController" * "edit" = "Drupal\contact\CategoryFormController" * } * } * uri_callback = "contact_category_uri", * config_prefix = "contact.category", * entity_keys = { * "id" = "id", * "label" = "label", * "uuid" = "uuid" * } * ) */class Category extends ConfigEntityBase implements CategoryInterface {
/** * The category ID. * * @var string */ public $id;
/** * The category UUID. * * @var string */ public $uuid;
/** * The category label. * * @var string */ public $label;
/** * List of recipient e-mail addresses. * * @var array */ public $recipients = array();
/** * An auto-reply message to send to the message author. * * @var string */ public $reply = '';
/** * Weight of this category (used for sorting). * * @var int */ public $weight = 0;
}
Friday 23 August 13
<?php
/** * @file * Definition of Drupal\contact\Plugin\Core\Entity\Category. */
namespace Drupal\contact\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;use Drupal\Core\Annotation\Plugin;use Drupal\Core\Annotation\Translation;
/** * Defines the contact category entity. * * @EntityType( * id = "contact_category", * label = @Translation("Category"), * module = "contact", * controllers = { * controller_class = "Drupal\contact\CategoryStorageController", * list = "Drupal\contact\CategoryListController", * form = { * "add" = "Drupal\contact\CategoryFormController" * "edit" = "Drupal\contact\CategoryFormController" * } * } * uri_callback = "contact_category_uri", * config_prefix = "contact.category", * entity_keys = { * "id" = "id", * "label" = "label", * "uuid" = "uuid" * } * ) */class Category extends ConfigEntityBase implements CategoryInterface {
/** * The category ID. * * @var string */ public $id;
/** * The category UUID. * * @var string */ public $uuid;
/** * The category label. * * @var string */ public $label;
/** * List of recipient e-mail addresses. * * @var array */ public $recipients = array();
/** * An auto-reply message to send to the message author. * * @var string */ public $reply = '';
/** * Weight of this category (used for sorting). * * @var int */ public $weight = 0;
}
Friday 23 August 13
<?php
/** * @file * Definition of Drupal\contact\Plugin\Core\Entity\Category. */
namespace Drupal\contact\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;use Drupal\Core\Annotation\Plugin;use Drupal\Core\Annotation\Translation;
/** * Defines the contact category entity. * * @Plugin( * id = "contact_category", * label = @Translation("Category"), * module = "contact", * controllers = { * controller_class = "Drupal\Core\Config\Entity\ConfigStorageController", * list = "Drupal\contact\CategoryListController", * form = { * "add" = "Drupal\contact\CategoryFormController" * } * }, * uri_callback = "contact_category_uri", * config_prefix = "contact.category", * entity_keys = { * "id" = "id", * "label" = "label", * "uuid" = "uuid" * } * ) */class Category extends ConfigEntityBase implements ContactInterface {
/** * The category ID. * * @var string */ public $id;
/** * The category UUID. * * @var string */ public $uuid;
/** * The category label. * * @var string */ public $label;
/** * List of recipient e-mail addresses. * * @var array */ public $recipients = array();
/** * An auto-reply message to send to the message author. * * @var string */ public $reply = '';
/** * Weight of this category (used for sorting). * * @var int */ public $weight = 0;
}
Friday 23 August 13
<?php
/** * @file * Definition of Drupal\contact\Plugin\Core\Entity\Category. */
namespace Drupal\contact\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;use Drupal\Core\Annotation\Plugin;use Drupal\Core\Annotation\Translation;
/** * Defines the contact category entity. * * @EntityType( * id = "contact_category", * label = @Translation("Category"), * module = "contact", * controllers = { * controller_class = "Drupal\Core\Config\Entity\ConfigStorageController", * list = "Drupal\contact\CategoryListController", * form = { * "add" = "Drupal\contact\CategoryFormController" * "edit" = "Drupal\contact\CategoryFormController" * } * } * uri_callback = "contact_category_uri", * config_prefix = "contact.category", * entity_keys = { * "id" = "id", * "label" = "label", * "uuid" = "uuid" * } * ) */class Category extends ConfigEntityBase implements ContactInterface {
/** * The category ID. * * @var string */ public $id;
/** * The category UUID. * * @var string */ public $uuid;
/** * The category label. * * @var string */ public $label;
/** * List of recipient e-mail addresses. * * @var array */ public $recipients = array();
/** * An auto-reply message to send to the message author. * * @var string */ public $reply = '';
/** * Weight of this category (used for sorting). * * @var int */ public $weight = 0;
}
Friday 23 August 13
<?php
/** * @file * Definition of Drupal\contact\Plugin\Core\Entity\Category. */
namespace Drupal\contact\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;use Drupal\Core\Annotation\Plugin;use Drupal\Core\Annotation\Translation;
/** * Defines the contact category entity. * * @Plugin( * id = "contact_category", * label = @Translation("Category"), * module = "contact", * controller_class = "Drupal\Core\Config\Entity\ConfigStorageController", * list_controller_class = "Drupal\contact\CategoryListController", * form_controller_class = { * "default" = "Drupal\contact\CategoryFormController" * }, * uri_callback = "contact_category_uri", * config_prefix = "contact.category", * entity_keys = { * "id" = "id", * "label" = "label", * "uuid" = "uuid" * } * ) */class Category extends ConfigEntityBase {
/** * The category ID. */ public $id;
/** * The category UUID. */ public $uuid;
/** * The category label. */ public $label;
/** * List of recipient e-mail addresses. */ public $recipients = array();
/** * An auto-reply message to send to the message author. */ public $reply = '';
/** * Weight of this category (used for sorting). */ public $weight = 0;
}
Friday 23 August 13
id: feedbackuuid: de77e4f3-f94b-41a5-ad05-5c32fa08444flabel: 'Website feedback'recipients: - ''reply: ''weight: '0'langcode: und
contact.category.feedback.yml
Friday 23 August 13
(config) entity API
• entity_load
• entity_save
• $object->any_method()
Friday 23 August 13
Deployment
Friday 23 August 13
Database
Development environment
ActiveDirectory
1
Friday 23 August 13
Database
Development environment
ActiveDirectory
1
Friday 23 August 13
Database
Development environment
ActiveDirectory
1
2
Friday 23 August 13
Database
Production environment
StagingDirectory
ActiveDirectory
3
admin/config/development/sync
Friday 23 August 13
Database
Production environment
StagingDirectory
ActiveDirectory
3
4admin/config/development/sync
Friday 23 August 13
Demo time
• No partial imports !
Friday 23 August 13
Drush integration
Friday 23 August 13
Advanced workflows
• https://drupal.org/sandbox/dereine/2057465
Friday 23 August 13
Don’t hack core
Friday 23 August 13
Don’t hack active config
Friday 23 August 13
State API
Drupal::state()->set('update.last_check', $now);//...$last_check = Drupal::state()->get('update.last_check') ?: 0;
Only useful for this environment? Use state().
Friday 23 August 13
Configuration schema
Friday 23 August 13
system.maintenance.yml
enabled: '0'message: '@site is currently under maintenance. We should be back shortly. Thank you for your patience.'
Friday 23 August 13
system.schema.yml
system.maintenance: type: mapping label: 'Maintenance mode' mapping: "enabled": type: boolean label: "Put site into maintenance mode" "message": type: text label: "Message to display when in maintenance mode"
Friday 23 August 13
Basic scalar types from typed data
boolean: label: 'Boolean' class: '\Drupal\Core\TypedData\Type\Boolean'email: label: 'Email' class: '\Drupal\Core\TypedData\Type\Email'integer: label: 'Integer' class: '\Drupal\Core\TypedData\Type\Integer'string: label: 'String' class: '\Drupal\Core\TypedData\Type\String'uri: label: 'Uri' class: '\Drupal\Core\TypedData\Type\Uri'
Friday 23 August 13
Basic data types for configuration
undefined: label: 'Undefined' class: '\Drupal\Core\Config\Schema\Property'mapping: label: Mapping class: '\Drupal\Core\Config\Schema\Mapping'sequence: label: Sequence class: '\Drupal\Core\Config\Schema\Sequence'
Friday 23 August 13
Simple extended data types# Human readable string that must be plain text and editable with a text field.label: type: string label: 'Label' translatable: true
# Internal Drupal pathpath: type: string label: 'Path'
# Human readable string that can contain multiple lines of text or HTML.text: type: string label: 'Text' translatable: true
Friday 23 August 13
Complex extended data type
# Mail text with subject and body parts.mail: type: mapping label: "Mail" mapping: "subject": type: text label: "Subject" "body": type: text label: "Body"
Friday 23 August 13
Config inspector module
Friday 23 August 13
Context system,Events & Overrides
Friday 23 August 13
global $conf;
$conf['system.maintenance']['message'] = 'Sorry, our site is down now.';
Global overrides
Friday 23 August 13
class ConfigGlobalOverrideSubscriber implements EventSubscriberInterface {
static function getSubscribedEvents() { $events['config.init'][] = array('configInit', 30); return $events; }
public function configInit(ConfigEvent $event) { global $conf;
$config = $event->getConfig(); if (isset($conf[$config->getName()])) { $config->setOverride($conf[$config->getName()]); } }}
Global overrides
Friday 23 August 13
Break out of contexts
// Enter the override-free context, so we can ensure no overrides are applied.config_context_enter('config.context.free');
// Get system site maintenance message text from the original config.$message = config('system.maintenance')->get('message');
// Leave the override-free context.config_context_leave();
Friday 23 August 13
Get into contexts
// Enter a user specific context.$context = config_context_enter("Drupal\\user\\UserConfigContext");// Set the account to use on the context.$context->setAccount($account);
$mail_config = Drupal::config('user.mail');
// Do stuff...
config_context_leave();
Friday 23 August 13
Language overridesblock.block.bartik.login.yml
id: bartik.loginuuid: 7012ebfd-7083-47ef-b...weight: '0'status: '1'langcode: enregion: sidebar_firstplugin: user_login_blocksettings: label: 'User login' module: user label_display: visible cache: '-1'......
locale.hu.block.block.bartik.login.yml
settings: label: 'Belépés'
locale.nl.block.block.bartik.login.yml
settings: label: 'Inloggen'
Friday 23 August 13
recap and advice
• key names/properties should have meaning
• Use config entities instead of tables
• Use getters/setters/methods on entities
• Include config schema (translation!)
• Upgrade functions available in update.inc
Friday 23 August 13
Please try it out!
• #drupal-cmi - Dedicated IRC channel
• docs - https://drupal.org/node/1667894
• help along - http://drupal.org/core-mentoring-hours
Friday 23 August 13
• http://groups.drupal.org/cmi - Discussion
• http://v.gd/cmi_issues - Issues
• http://groups.drupal.org/core - Core announcements
• #drupal-cmi - Dedicated IRC channel
• http://drupal.org/core-mentoring-hours
Friday 23 August 13
Questions ?
Friday 23 August 13
Thanks@heyrocker
@webchick
@moshe_weitzman
@GaborHojtsy
@alexpott
Friday 23 August 13