On Github fmitchell / d8apifuncnyccamp2014
Created by Fredric Mitchell / @fredricmitchell
http://brightplumbox.com/d8apifuncnyccamp2014/#/
Senior Developer at Phase2 Technology
Drupal, DRY / KISS, Strat. Comm., Graphic Novels
Wrapper for htmlspecialchars with UTF-8 encoding
Wrap <em> around String:checkPlain()
$text = t(“@name's blog”, array('@name' => $value)) // Note: @name (String::checkPlain()) vs. %name (String::placeholder()) vs. !name
$link = l(t('Link text'), 'node/34', array( 'attributes' => array( 'class' => array('about-link'), ) )); // Note: automatic alias replacement via url()
$render = array( 'first_para' => array( '#type' => 'markup', '#markup' => 'A first paragraph', ), 'second_para' => array( array('first item', 'second item', 'third item'), '#theme' => 'item_list', ), ); return drupal_render($render);
_theme() is an internal function
D7
// Theme a table with header and row data. $markup = theme('table', array( 'header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'my-module-table') )); // Render a pager. $markup .= theme('pager');
D8
$table = array( '#type' => 'table', '#header' => $header, '#rows' => $rows, '#attributes' => array('id' => 'my-module-table'), ); $markup = drupal_render($table); // Pager is not an element type, use #theme directly. $pager = array('#theme' => 'pager'); $markup .= drupal_render($pager);
Yes. I was just getting there.
node_load_multiple wraps around entity_load_multiple
entity_load_multiple wraps around $controller->loadMultiple()
$controller is the StorageController for the entity
The storage controller is likely DatabaseStorageController class
$nodes = entity_load_multiple('node', $nids = array()) // Note: Cached
node_view_multiple wraps around entity_view_multiple
entity_view_multiple wraps around $render_controller->viewMultiple()
$render_controller is the getViewBuilder for the entity
The view builder controller is likely EntityViewBuilder class
$nodes = entity_view_multiple($nodes);
node_save() is gone
entity_create wraps around $controller->create()
$controller is the StorageController for the entity
The storage controller is likely DatabaseStorageController class
// Create a new forum instance. $node = entity_create('node', array('otherValue' => 'foo')); // Save entity to the database. $node->save(); // Note: nothing is returned
D7
function mymodule_menu() { $items['abc/def'] = array( 'page callback' => 'mymodule_abc_view', ); return $items; } function mymodule_abc_view($ghi = 0, $jkl = '') { // ... }
D8
mymodule.add_page: path: 'abc/def' defaults: _content: '\Drupal\mymodule\Controller\MyModuleController::addPage' _title: 'My Module' requirements: _permission: 'administer mymodule foobar'
Uses the new routing system from Symfony
$request = \Drupal::request(); $route = $request()->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
$request = \Drupal::request(); $node = $request()->attributes->get('node'); $type = $node->type; // Note: Use instead of arg()
Discussion: https://drupal.org/node/2124749
Possibly have $request, $route_match, and $context_container as separate objects.
$tree = menu_tree_page_data('main-menu');
// Build a HTML menu $tree = menu_tree_page_data('main-menu'); $menu = menu_tree_output($tree, 1); return drupal_render($menu);
D7
// Get a taxonomy object. $vocabulary = taxonomy_vocabulary_machine_name_load('forums'); $options[$vocabulary->vid] = $vocabulary->name;
D8
// Get a taxonomy object. $vocabulary = entity_load('taxonomy_vocabulary', 'forums'); $options[$vocabulary->id()] = $vocabulary->label();
// Get a taxonomy object. $v = entity_load('taxonomy_vocabulary', 'forums'); // Build an array of taxonomy terms. $terms = taxonomy_get_tree($v->id()); foreach ($terms as $term) { $options[$term->tid] = $term->name; }
Wraps around entity_load('field_config', ...)
// Get info a field name. $fieldInfo = \Drupal\field\Field::fieldInfo(); $fieldInfo->getField($entity_type, $field_name);
Wraps around entity_load_multiple('field_instance_config', ...)
// Get info on field name. $fieldInfo = \Drupal\field\Field::fieldInfo(); // Get info on instance of field name from a bundle. $fieldInfo->getInstance('node', 'article', 'field_name');
The field configuration (field_config) is now an entity type
entity_create() invokes the create method of the StorageController
The field_config entity uses FieldConfigStorageController
All other methods are in \Drupal\field\Entity\FieldConfig
D7
// Note: Requires proper field / instance data array which you can get from a features export. $field_bases = array(); // Exported field_base: 'field_sc_html' $field_bases['field_sc_html'] = array( 'active' => 1, 'cardinality' => 1, 'deleted' => 0, 'entity_types' => array(), 'field_name' => 'field_sc_html', 'foreign keys' => array( 'format' => array( 'columns' => array( 'format' => 'format', ), 'table' => 'filter_format', ), ), 'indexes' => array( 'format' => array( 0 => 'format', ), ), 'locked' => 0, 'module' => 'text', 'settings' => array(), 'translatable' => 0, 'type' => 'text_long', ); field_create_field($field_bases);
D8
$field = entity_create('field_config', array( 'name' => 'field_description', 'entity_type' => 'taxonomy_term', 'type' => 'text', )); $field->save();
The field instance configuration (field_instance_config) is now an entity type
entity_create() invokes the create method of the StorageController
The field_instance_config entity uses FieldInstanceConfigStorageController
All other methods are in \Drupal\field\Entity\FieldInstanceConfig
D7
// Note: Requires proper field / instance data array which you can get from a features export. $field_instances = array(); // Exported field_instance: 'bean-field_sc_html' $field_instances['bean-field_sc_html'] = array( 'bundle' => 'oms_sidebar_content', 'default_value' => NULL, 'deleted' => 0, 'description' => '', 'display' => array( 'default' => array( 'label' => 'above', 'settings' => array(), 'type' => 'hidden', 'weight' => 0, ), ), 'entity_type' => 'bean', 'field_name' => 'field_sc_html', 'label' => 'HTML', 'required' => 0, 'settings' => array( 'text_processing' => 1, 'user_register_form' => FALSE, ), 'widget' => array( 'active' => 1, 'module' => 'text', 'settings' => array( 'rows' => 5, ), 'type' => 'text_textarea', 'weight' => 2, ), ); field_create_instance($field_instances);
D8
$field_instance = entity_create('field_instance_config', array( 'field_name' => 'field_description', 'entity_type' => 'taxonomy_term', 'bundle' => 'tags', 'label' => 'Custom tag description', )); $field_instance->save();
D7
function mymodule_install_fields($fields, $instance_fields, $type = 'node', $bundle) { foreach ($fields as $field) { // Create the field if it doesn't exist. if (!field_info_field($field['field_name'])) { field_create_field($field); } } unset($field); foreach ($instance_fields as $field) { if (!field_info_instance($type, $field['field_name'], $bundle)) { field_create_instance($field); } } }
// Updating field. $field->cardinality = 2; $field->save(); // Deleting field. entity_load('field_config', 'field_name')->delete(); // Deleting instance. entity_load('field_instance_config', 'field_instance_name')->delete();
$data = array( 'key1' => 'value1', 'key2' => 'value2', ); // Call all modules implementing hook_my_data_alter \Drupal::moduleHandler()->alter('my_data', $data); // Note: Use sparingly. hook_theme() is preferred for overriding styles.
function mymodule_form_alter(&$form, &$form_state) { $form['new_checkbox'] = array( '#type' => 'checkbox', '#title' => t ('Subscribe'), ); );
getFormId() method defines id to alter
/** * @file * Contains \Drupal\example\Form\ExampleForm. */ namespace Drupal\example\Form; use Drupal\Core\Form\FormBase; /** * Implements an example form. */ class ExampleForm extends FormBase { /** * {@inheritdoc}. */ public function getFormId() { return 'example_form'; } }
function mymodule_form_example_form_alter() { ... );
https://drupal.org/node/2117411
\Drupal::moduleHandler->invokeAll($hook, $args);
\Drupal::moduleHandler->getImplementations($hook);
use Drupal\Component\Utility\UrlHelper; // URL: http://mysite.com?text=foo&date=2013-09-14 $url = \Drupal::request()->query->all(); // May not be best way $param = UrlHelper::filterQueryParameters($url); // Values // $param['text'] = foo // $param['date'] = 2013-09-14
// Path to a file $path = drupal_get_path('theme', 'mytheme') . '/mycustom.js';
D7: global $user
D8: \Drupal::currentUser()
https://drupal.org/node/2032447
$account = \Drupal::currentUser(); if ($account->id() == 1) { return "Hiya, boss!"; } // $account is not an actual User object, but UserSession object // Extends AccountInterface class
// Load node.admin.inc from the node module. \Drupal::moduleHandler->loadInclude('node', 'inc', 'node.admin');
// Query articles $query = new EntityFieldQuery(); $query ->entityCondition('entity_type', 'node') ->entityCondition('bundle', 'article') ->propertyCondition('status', 1); $result = $query->execute(); $nids = array_keys($result['node']); $nodes = node_load_multiple($nids);
EFQ presentation at http://bit.ly/top10efq
$query = \Drupal::entityQuery('taxonomy_term') ->condition('tid', $term->id()) ->condition('vid', $term->bundle()) ->range(0, 1) ->count() ->execute();
https://drupal.org/node/1827278
What about functions completely removed?
Gone!
https://drupal.org/node/2169605
// within CKEditor public function settingsForm(array $form, array &$form_state, EditorEntity $editor) { $ckeditor_settings_toolbar = array( '#theme' => 'ckeditor_settings_toolbar', '#editor' => $editor, '#plugins' => $this->ckeditorPluginManager->getButtons(), ); $form['toolbar'] = array( '#type' => 'container', '#attached' => array( 'library' => array('ckeditor/drupal.ckeditor.admin'), 'js' => array( array( 'type' => 'setting', 'data' => array('ckeditor' => array( 'toolbarAdmin' => drupal_render($ckeditor_settings_toolbar), )), ) ), ), '#attributes' => array('class' => array('ckeditor-toolbar-configuration')), );
Technically, no.
#attached could be a +3
drupal_add_js, drupal_add_css, drupal_add_library
Contribute to Examples: https://drupal.org/project/examples
Read docs: https://drupal.org/developing/api/8
Scaffold: https://github.com/hechoendrupal/DrupalAppConsole
Slides: http://brightplumbox.com/d8apifuncnyccamp2014/#/
Slides Repo: https://github.com/fmitchell/d8apifuncnyccamp2014