13.07.2015 Views

Drupal 8 Configuration system for coders and site builders

Drupal 8 Configuration system for coders and site builders

Drupal 8 Configuration system for coders and site builders

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

What problems are wetrying to solve?DevLiveadmin/config/foonode/4admin/config/foonode/4Setting 1Setting 2textlabelSaveTESTtest test test testtest test test testtest test test testtest testSetting 1Setting 2old textlabelSaveWelcomeThis is realcontent on thelive <strong>site</strong> that endusers are viewingDatabaseDatabaseDanger!Want to bring over configurationchanges from dev, but notoverwrite live content!Saturday 16 November 13


What problems are wetrying to solve?variable_set()/variable_get()napkinsdb_select()/db_update()/db_delete()hook_update_N()drush fu$conf[...];ctools_export_object()/ctools_export_load_object()Saturday 16 November 13http://www.flickr.com/photos/bean/322616749


The solution• Files using the YAML specification• Active <strong>and</strong> staging directory• Cached in the database using a st<strong>and</strong>ardcache interface• Config directory changed via settings.php• This is all pluggableSaturday 16 November 13


The anatomy of aconfiguration fileSaturday 16 November 13


Saturday 16 November 13<strong>system</strong>.<strong>site</strong>.yml


Saturday 16 November 13<strong>system</strong>.<strong>site</strong>.yml


Saturday 16 November 13<strong>system</strong>.<strong>site</strong>.yml


<strong>system</strong>.<strong>site</strong>.ymlname: '<strong>Configuration</strong> management'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: ''404: ''front: nodeSaturday 16 November 13


The API<strong>Drupal</strong>::config()->get()->set()->save()Saturday 16 November 13


Saturday 16 November 13Accessing data


$<strong>site</strong>_name = <strong>Drupal</strong>::config('<strong>system</strong>.<strong>site</strong>')->get('name');name: '<strong>Configuration</strong> management'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: ''404: ''front: nodeSaturday 16 November 13


$page_data = <strong>Drupal</strong>::config('<strong>system</strong>.<strong>site</strong>')->get('page');name: '<strong>Configuration</strong> management'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: ''404: ''front: nodeSaturday 16 November 13


$frontpage = <strong>Drupal</strong>::config('<strong>system</strong>.<strong>site</strong>')->get('page.front');name: '<strong>Configuration</strong> management'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: ''404: ''front: nodeSaturday 16 November 13


$all_the_data = <strong>Drupal</strong>::config('<strong>system</strong>.<strong>site</strong>')->get();name: '<strong>Configuration</strong> management'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: ''404: ''front: nodeSaturday 16 November 13


Saturday 16 November 13Saving data


<strong>Drupal</strong>::config('<strong>system</strong>.<strong>site</strong>')->set('name', 'CMI is good')->save();name: 'CMI is good'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: ''404: ''front: nodeSaturday 16 November 13


<strong>Drupal</strong>::config('<strong>system</strong>.<strong>site</strong>')->set('name', 'CMI is great')->set('page', array(403 => 'access-denied',404 => 'not-found',front => 'user',))->save();name: 'CMI is great'mail: admin@example.comslogan: 'makes <strong>Drupal</strong> 8 cex -y'page:403: access-denied404: not-foundfront: userSaturday 16 November 13


Saturday 16 November 13


simple settings• <strong>system</strong>_settings_<strong>for</strong>m is dead• create your own submit callback• you are responsible <strong>for</strong> saving configuration• ship with default configuration fileSaturday 16 November 13


{language}{field_config}{date_<strong>for</strong>mat_type}{filter_<strong>for</strong>mat}{field_config_instance}{date_<strong>for</strong>mat_locale}{node_type}{role_permission}{role}{date_<strong>for</strong>mats}{<strong>system</strong>}{variable}{filter}Saturday 16 November 13


Saturday 16 November 13Config all the things!


Saturday 16 November 13Config entities


**Saturday 16 * November The 13categoryID.use <strong>Drupal</strong>\Core\Config\Entity\ConfigEntityBase;use <strong>Drupal</strong>\Core\Annotation\Plugin;use <strong>Drupal</strong>\Core\Annotation\Translation;/*** Defines the contact category entity.** @EntityType(* id = "contact_category",* label = @Translation("Category"),* module = "contact",* controllers = {* controller_class = "<strong>Drupal</strong>\contact\CategoryStorageController",* list = "<strong>Drupal</strong>\contact\CategoryListController",* <strong>for</strong>m = {* "add" = "<strong>Drupal</strong>\contact\CategoryFormController"* "edit" = "<strong>Drupal</strong>\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 {


**Saturday 16 * November The 13categoryID.use <strong>Drupal</strong>\Core\Config\Entity\ConfigEntityBase;use <strong>Drupal</strong>\Core\Annotation\Plugin;use <strong>Drupal</strong>\Core\Annotation\Translation;/*** Defines the contact category entity.** @EntityType(* id = "contact_category",* label = @Translation("Category"),* module = "contact",* controllers = {* controller_class = "<strong>Drupal</strong>\contact\CategoryStorageController",* list = "<strong>Drupal</strong>\contact\CategoryListController",* <strong>for</strong>m = {* "add" = "<strong>Drupal</strong>\contact\CategoryFormController"* "edit" = "<strong>Drupal</strong>\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 {


namespace <strong>Drupal</strong>\contact\Plugin\Core\Entity;use <strong>Drupal</strong>\Core\Config\Entity\ConfigEntityBase;use <strong>Drupal</strong>\Core\Annotation\Plugin;use <strong>Drupal</strong>\Core\Annotation\Translation;/*** Defines the contact category entity.** @Plugin(* id = "contact_category",* label = @Translation("Category"),* module = "contact",* controllers = {* controller_class = "<strong>Drupal</strong>\Core\Config\Entity\ConfigStorageController",* list = "<strong>Drupal</strong>\contact\CategoryListController",* <strong>for</strong>m = {* "add" = "<strong>Drupal</strong>\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.Saturday 16 November 13


**Saturday 16 * November The 13categoryID.use <strong>Drupal</strong>\Core\Config\Entity\ConfigEntityBase;use <strong>Drupal</strong>\Core\Annotation\Plugin;use <strong>Drupal</strong>\Core\Annotation\Translation;/*** Defines the contact category entity.** @EntityType(* id = "contact_category",* label = @Translation("Category"),* module = "contact",* controllers = {* controller_class = "<strong>Drupal</strong>\Core\Config\Entity\ConfigStorageController",* list = "<strong>Drupal</strong>\contact\CategoryListController",* <strong>for</strong>m = {* "add" = "<strong>Drupal</strong>\contact\CategoryFormController"* "edit" = "<strong>Drupal</strong>\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 {


*/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 <strong>for</strong> sorting).*/public $weight = 0;Saturday 16 November 13


contact.category.feedback.ymlid: feedbackuuid: de77e4f3-f94b-41a5-ad05-5c32fa08444flabel: 'Web<strong>site</strong> feedback'recipients:- ''reply: ''weight: '0'langcode: undSaturday 16 November 13


(config) entity API• entity_load• entity_save• $object->any_method()Saturday 16 November 13


Saturday 16 November 13Deployment


Development environment1DatabaseActiveDirectorySaturday 16 November 13


Development environment1DatabaseActiveDirectorySaturday 16 November 13


Development environment1Database2ActiveDirectorySaturday 16 November 13


Production environmentadmin/config/development/syncDatabase3StagingDirectoryActiveDirectorySaturday 16 November 13


Production environment4admin/config/development/syncDatabase3StagingDirectoryActiveDirectorySaturday 16 November 13


Demo time• Full import / export• Single import / export• No partial imports supported on CLI!Saturday 16 November 13


Saturday 16 November 13Drush integration


Advanced workflows• https://drupal.org/s<strong>and</strong>box/dereine/2057465• use git pre-commit hooks with definedconfig directories in settings.phpSaturday 16 November 13


Saturday 16 November 13Don’t hack core


Saturday 16 November 13Don’t hack active config


State APIOnly useful <strong>for</strong> this environment? Use state().<strong>Drupal</strong>::state()->set('update.last_check', $now);//...$last_check = <strong>Drupal</strong>::state()->get('update.last_check') ?: 0;Saturday 16 November 13


Saturday 16 November 13<strong>Configuration</strong> schema


<strong>system</strong>.maintenance.ymlenabled: '0'message: '@<strong>site</strong> is currently under maintenance. Weshould be back shortly. Thank you <strong>for</strong> your patience.'Saturday 16 November 13


<strong>system</strong>.schema.yml<strong>system</strong>.maintenance:type: mappinglabel: 'Maintenance mode'mapping:"enabled":type: booleanlabel: "Put <strong>site</strong> into maintenance mode""message":type: textlabel: "Message to display when in maintenance mode"Saturday 16 November 13


Basic scalar types from typed databoolean:label: 'Boolean'class: '\<strong>Drupal</strong>\Core\TypedData\Type\Boolean'email:label: 'Email'class: '\<strong>Drupal</strong>\Core\TypedData\Type\Email'integer:label: 'Integer'class: '\<strong>Drupal</strong>\Core\TypedData\Type\Integer'string:label: 'String'class: '\<strong>Drupal</strong>\Core\TypedData\Type\String'uri:label: 'Uri'class: '\<strong>Drupal</strong>\Core\TypedData\Type\Uri'Saturday 16 November 13


Basic data types <strong>for</strong> configurationundefined:label: 'Undefined'class: '\<strong>Drupal</strong>\Core\Config\Schema\Property'mapping:label: Mappingclass: '\<strong>Drupal</strong>\Core\Config\Schema\Mapping'sequence:label: Sequenceclass: '\<strong>Drupal</strong>\Core\Config\Schema\Sequence'Saturday 16 November 13


Simple extended data types# Human readable string that must be plain text <strong>and</strong> editablewith a text field.label:type: stringlabel: 'Label'translatable: true# Internal <strong>Drupal</strong> pathpath:type: stringlabel: 'Path'# Human readable string that can contain multiple lines of textor HTML.text:type: stringlabel: 'Text'translatable: trueSaturday 16 November 13


Complex extended data type# Mail text with subject <strong>and</strong> body parts.mail:type: mappinglabel: "Mail"mapping:"subject":type: textlabel: "Subject""body":type: textlabel: "Body"Saturday 16 November 13


Saturday 16 November 13Config inspector module


Context <strong>system</strong>,Events & OverridesSaturday 16 November 13


Global overridesglobal $conf;$conf['<strong>system</strong>.maintenance']['message'] ='Sorry, our <strong>site</strong> is down now.';Saturday 16 November 13


Global overridesclass ConfigGlobalOverrideSubscriber implementsEventSubscriberInterface {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()]);}Saturday 16 November 13


Break out of contexts// Enter the override-free context, so we can ensure nooverrides are applied.config_context_enter('config.context.free');// Get <strong>system</strong> <strong>site</strong> maintenance message text from the originalconfig.$message = config('<strong>system</strong>.maintenance')->get('message');// Leave the override-free context.config_context_leave();Saturday 16 November 13


Get into contexts// Enter a user specific context.$context = config_context_enter("<strong>Drupal</strong>\\user\\UserConfigContext");// Set the account to use on the context.$context->setAccount($account);$mail_config = <strong>Drupal</strong>::config('user.mail');// Do stuff...config_context_leave();Saturday 16 November 13


Language overridesblock.block.bartik.login.ymlid: bartik.loginuuid: 7012ebfd-7083-47ef-b...weight: '0'status: '1'langcode: enregion: sidebar_firstplugin: user_login_blocksettings:label: 'User login'module: userlabel_display: visiblecache: '-1'......locale.hu.block.block.bartik.login.ymlsettings:label: 'Belépés'locale.nl.block.block.bartik.login.ymlsettings:label: 'Inloggen'Saturday 16 November 13


ecap <strong>and</strong> 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.incSaturday 16 November 13


Please try it out!• #drupal-cmi - Dedicated IRC channel• docs - https://drupal.org/node/1667894• help along - http://drupal.org/core-mentoring-hoursSaturday 16 November 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-hoursSaturday 16 November 13


Saturday 16 November 13Questions ?


Thanks@heyrocker@webchick@moshe_weitzman@GaborHojtsy@alexpottSaturday 16 November 13

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!