diff --git a/core/modules/block/custom_block/custom_block.install b/core/modules/block/custom_block/custom_block.install index 2f9ecd0..6345b7f 100644 --- a/core/modules/block/custom_block/custom_block.install +++ b/core/modules/block/custom_block/custom_block.install @@ -62,24 +62,9 @@ function custom_block_schema() { 'not null' => TRUE, 'default' => '', ), - 'tnid' => array( - 'description' => 'The translation set id for this node, which equals the node id of the source post in each set.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'translate' => array( - 'description' => 'A boolean indicating whether this translation page needs to be updated.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), ), 'indexes' => array( 'block_custom_type' => array(array('type', 4)), - 'tnid' => array('tnid'), - 'translate' => array('translate'), ), 'unique keys' => array( 'vid' => array('vid'), diff --git a/core/modules/block/custom_block/custom_block.js b/core/modules/block/custom_block/custom_block.js index a35d438..fb0905a 100644 --- a/core/modules/block/custom_block/custom_block.js +++ b/core/modules/block/custom_block/custom_block.js @@ -24,6 +24,22 @@ Drupal.behaviors.customBlockDetailsSummaries = { return Drupal.t('No revision'); }); + + $context.find('fieldset.custom-block-translation-options').drupalSetSummary(function (context) { + var $context = $(context); + var translate; + var $checkbox = $context.find('.form-item-translation-translate input'); + + if ($checkbox.size()) { + translate = $checkbox.is(':checked') ? Drupal.t('Needs to be updated') : Drupal.t('Does not need to be updated'); + } + else { + $checkbox = $context.find('.form-item-translation-retranslate input'); + translate = $checkbox.is(':checked') ? Drupal.t('Flag other translations as outdated') : Drupal.t('Do not flag other translations as outdated'); + } + + return translate; + }); } }; diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module index 42b77c7..148ab06 100644 --- a/core/modules/block/custom_block/custom_block.module +++ b/core/modules/block/custom_block/custom_block.module @@ -88,6 +88,19 @@ function custom_block_menu() { 'description' => 'Add custom block', 'file' => 'custom_block.pages.inc', ); + $items['block/%custom_block_machine_name'] = array( + 'title callback' => 'entity_page_label', + 'title arguments' => array(1), + 'page callback' => 'custom_block_page_view', + 'page arguments' => array(1), + 'access arguments' => array('view custom blocks'), + 'file' => 'custom_block.pages.inc', + ); + $items['block/%custom_block_machine_name/view'] = array( + 'title' => 'View', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); $items['block/%custom_block_machine_name/edit'] = array( 'title' => 'Edit', 'page callback' => 'custom_block_edit', @@ -101,7 +114,7 @@ function custom_block_menu() { $items['block/%custom_block_machine_name/delete'] = array( 'title' => 'Delete', 'page callback' => 'drupal_get_form', - 'page arguments' => array('custom_block_delete_confirm', 1), + 'page arguments' => array('custom_block_delete_form', 1), 'access arguments' => array('administer blocks'), 'weight' => 1, 'type' => MENU_LOCAL_TASK, @@ -112,6 +125,18 @@ function custom_block_menu() { } /** + * Implements hook_permission(). + */ +function custom_block_permission() { + return array( + 'view custom blocks' => array( + 'title' => t('View custom blocks on a page'), + 'description' => t('View custom blocks on a page of their own.') + ) + ); +} + +/** * Implements hook_theme(). */ function custom_block_theme($existing, $type, $theme, $path) { @@ -196,7 +221,11 @@ function custom_block_type_uri(CustomBlockType $block_type) { /** * Implements hook_entity_info(). */ -function custom_block_entity_info_alter(&$types) { +function custom_block_entity_info(&$types) { + // Add a translation handler for fields if the language module is enabled. + if (module_exists('language')) { + $types['custom_block']['translation']['custom_block'] = TRUE; + } foreach (config_get_storage_names_with_prefix('custom_block.type.') as $config_name) { $config = config($config_name); $types['custom_block']['bundles'][$config->get('id')] = array( diff --git a/core/modules/block/custom_block/custom_block.pages.inc b/core/modules/block/custom_block/custom_block.pages.inc index 958a610..45651ec 100644 --- a/core/modules/block/custom_block/custom_block.pages.inc +++ b/core/modules/block/custom_block/custom_block.pages.inc @@ -8,6 +8,31 @@ use Drupal\custom_block\Plugin\Core\Entity\CustomBlock; /** + * Page callback: Displays a single node. + * + * @param Drupal\custom_block\Plugin\Core\Entity\CustomBlock $block + * The node entity. + * + * @return + * A page array suitable for use by drupal_render(). + * + * @see custom_block_menu() + */ +function custom_block_page_view(CustomBlock $block) { + // If there is a menu link to this node, the link becomes the last part + // of the active trail, and the link name becomes the page title. + // Thus, we must explicitly set the page title to be the block title. + drupal_set_title($block->label()); + $uri = $block->uri(); + // Set the block path as the canonical URL to prevent duplicate content. + drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'])), TRUE); + // Set the non-aliased path as a default shortlink. + drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array('alias' => TRUE))), TRUE); + return entity_view($block, 'full'); +} + + +/** * Page callback: Displays add custom block links for available types. * * Redirects to block/add/[type] if only one custom block type is available. diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php index 8cfdbdd..a1aa4ae 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php @@ -9,12 +9,12 @@ use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityFormControllerNG; /** * Form controller for the custom block edit forms. */ -class CustomBlockFormController extends EntityFormController { +class CustomBlockFormController extends EntityFormControllerNG { /** * Prepares the custom block object. @@ -26,10 +26,10 @@ class CustomBlockFormController extends EntityFormController { */ protected function prepareEntity(EntityInterface $block) { // Set up default values, if required. - $block_type = entity_load('custom_block_type', $block->type); + $block_type = entity_load('custom_block_type', $block->type->value); // If this is a new custom block, fill in the default values. - if (isset($block->bid)) { - $block->log = NULL; + if (isset($block->bid->value)) { + $block->set('log', NULL); } // Always use the default revision setting. $block->setNewRevision($block_type->revision); @@ -45,14 +45,14 @@ public function form(array $form, array &$form_state, EntityInterface $block) { // Override the default CSS class name, since the user-defined custom block // type name in 'TYPE-block-form' potentially clashes with third-party class // names. - $form['#attributes']['class'][0] = drupal_html_class('block-' . $block->type . '-form'); + $form['#attributes']['class'][0] = drupal_html_class('block-' . $block->type->value . '-form'); // Basic block information. // These elements are just values so they are not even sent to the client. foreach (array('bid', 'vid') as $key) { $form[$key] = array( '#type' => 'value', - '#value' => isset($block->$key) ? $block->$key : NULL, + '#value' => $block->$key->value, ); } @@ -60,14 +60,14 @@ public function form(array $form, array &$form_state, EntityInterface $block) { '#type' => 'textfield', '#title' => t('Block description'), '#required' => TRUE, - '#default_value' => $block->info, + '#default_value' => $block->info->value, '#weight' => -5, '#description' => t('A brief description of your block. Used on the Blocks administration page.', array('@overview' => url('admin/structure/block'))), ); $form['machine_name'] = array( '#type' => 'machine_name', - '#default_value' => $block->machine_name, + '#default_value' => $block->machine_name->value, '#machine_name' => array( 'exists' => 'custom_block_load', 'source' => array('info') @@ -76,11 +76,11 @@ public function form(array $form, array &$form_state, EntityInterface $block) { '#disabled' => !$block->isNew(), ); - $language_configuration = module_invoke('language', 'get_default_configuration', 'custom_block', $block->type); + $language_configuration = module_invoke('language', 'get_default_configuration', 'custom_block', $block->type->value); $form['langcode'] = array( '#title' => t('Language'), '#type' => 'language_select', - '#default_value' => $block->langcode, + '#default_value' => $block->langcode->value, '#languages' => LANGUAGE_ALL, '#access' => isset($language_configuration['language_hidden']) && !$language_configuration['language_hidden'], ); @@ -131,7 +131,7 @@ public function form(array $form, array &$form_state, EntityInterface $block) { '#type' => 'textarea', '#title' => t('Revision log message'), '#rows' => 4, - '#default_value' => !empty($block->log) ? $block->log : '', + '#default_value' => !empty($block->log->value) ? $block->log->value : '', '#description' => t('Briefly describe the changes you have made.'), ); @@ -139,20 +139,6 @@ public function form(array $form, array &$form_state, EntityInterface $block) { } /** - * Overrides Drupal\Core\Entity\EntityFormController::validate(). - */ - public function validate(array $form, array &$form_state) { - $block = $this->buildEntity($form, $form_state); - - foreach (module_implements('custom_block_validate') as $module) { - $function = $module . '_custom_block_validate'; - $function($block, $form, $form_state); - } - - parent::validate($form, $form_state); - } - - /** * Updates the custom block object by processing the submitted values. * * This function can be called by a "Next" button of a wizard to update the @@ -183,10 +169,10 @@ public function submit(array $form, array &$form_state) { */ public function save(array $form, array &$form_state) { $block = $this->getEntity($form_state); - $insert = empty($block->bid); + $insert = empty($block->bid->value); $block->save(); $watchdog_args = array('@type' => $block->bundle(), '%info' => $block->label()); - $block_type = entity_load('custom_block_type', $block->type); + $block_type = entity_load('custom_block_type', $block->type->value); $t_args = array('@type' => $block_type->label(), '%info' => $block->label()); if ($insert) { @@ -198,15 +184,15 @@ public function save(array $form, array &$form_state) { drupal_set_message(t('@type %info has been updated.', $t_args)); } - if ($block->bid) { - $form_state['values']['bid'] = $block->bid; - $form_state['bid'] = $block->bid; + if ($block->bid->value) { + $form_state['values']['bid'] = $block->bid->value; + $form_state['bid'] = $block->bid->value; if ($insert) { if ($theme = $block->getTheme()) { - $form_state['redirect'] = 'admin/structure/block/manage/custom_block:' . $block->machine_name . '/' . $theme; + $form_state['redirect'] = 'admin/structure/block/manage/custom_block:' . $block->machine_name->value . '/' . $theme; } else { - $form_state['redirect'] = 'admin/structure/block/manage/custom_block:' . $block->machine_name . '/' . variable_get('theme_default', 'stark'); + $form_state['redirect'] = 'admin/structure/block/manage/custom_block:' . $block->machine_name->value . '/' . variable_get('theme_default', 'stark'); } } else { @@ -233,8 +219,8 @@ public function delete(array $form, array &$form_state) { $destination = drupal_get_destination(); unset($_GET['destination']); } - $block = $this->getEntity($form_state); - $form_state['redirect'] = array('block/' . $block->bid . '/delete', array('query' => $destination)); + $block = $this->buildEntity($form, $form_state); + $form_state['redirect'] = array('block/' . $block->machine_name->value . '/delete', array('query' => $destination)); } } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php index 1d3dcb1..30f5265 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php @@ -7,7 +7,7 @@ namespace Drupal\custom_block; -use Drupal\Core\Entity\DatabaseStorageController; +use Drupal\Core\Entity\DatabaseStorageControllerNG; use Drupal\Core\Entity\EntityInterface; /** @@ -16,7 +16,7 @@ * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding * required special handling for custom block entities. */ -class CustomBlockStorageController extends DatabaseStorageController { +class CustomBlockStorageController extends DatabaseStorageControllerNG { /** * Overrides Drupal\Core\Entity\DatabaseStorageController::preSaveRevision(). @@ -57,4 +57,52 @@ function postSave(EntityInterface $block, $update) { } } + /** + * Implements \Drupal\Core\Entity\DataBaseStorageControllerNG::basePropertyDefinitions(). + */ + public function baseFieldDefinitions() { + $properties['bid'] = array( + 'label' => t('ID'), + 'description' => t('The custom block ID.'), + 'type' => 'integer_field', + 'read-only' => TRUE, + ); + $properties['uuid'] = array( + 'label' => t('UUID'), + 'description' => t('The custom block UUID.'), + 'type' => 'string_field', + ); + $properties['vid'] = array( + 'label' => t('Revision ID'), + 'description' => t('The revision ID.'), + 'type' => 'integer_field', + ); + $properties['langcode'] = array( + 'label' => t('Language code'), + 'description' => t('The comment language code.'), + 'type' => 'language_field', + ); + $properties['info'] = array( + 'label' => t('Subject'), + 'description' => t('The custom block name.'), + 'type' => 'string_field', + ); + $properties['machine_name'] = array( + 'label' => t('Machine name'), + 'description' => t('The custom block machine name.'), + 'type' => 'string_field', + ); + $properties['type'] = array( + 'label' => t('Block type'), + 'description' => t("The block type."), + 'type' => 'string_field', + ); + $properties['log'] = array( + 'label' => t('Revision log message'), + 'description' => t("The revision log message."), + 'type' => 'string_field', + ); + return $properties; + } + } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTranslationController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTranslationController.php new file mode 100644 index 0000000..860aef6 --- /dev/null +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTranslationController.php @@ -0,0 +1,59 @@ + 'additional_settings', + '#weight' => 100, + '#attributes' => array( + 'class' => array('custom-block-translation-options'), + ), + ); + } + } + + /** + * Overrides EntityTranslationController::entityFormTitle(). + */ + protected function entityFormTitle(EntityInterface $entity) { + $block_type = entity_load('custom_block_type', $entity->type->value); + return t('Edit @type @title', array('@type' => $block_type->label(), '@title' => $entity->label())); + } + + /** + * Overrides EntityTranslationController::entityFormTitle(). + * + * Custom Block menu paths are keyed by machine name, not id. + */ + protected function getPathInstance($path, $entity_id) { + $entity = entity_load('custom_block', $entity_id); + $wildcard = '%custom_block_machine_name'; + return str_replace($wildcard, $entity->machine_name->value, $path); + } +} diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php index e17e040..75484f9 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeFormController.php @@ -42,9 +42,16 @@ public function form(array $form, array &$form_state, EntityInterface $block_typ '#type' => 'checkbox', '#title' => t('Create new revision'), '#default_value' => $block_type->revision, - '#desciption' => t('Create a new revision by default for this block type.') + '#description' => t('Create a new revision by default for this block type.') ); + // @todo Remove this check once language settings are generalized. + if (module_exists('translation_entity')) { + $translation_form = $form; + $translation_form_state['translation_entity']['key'] = 'language_configuration'; + $form += translation_entity_enable_widget('custom_block', $block_type->id(), $translation_form, $translation_form_state); + } + $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', @@ -71,6 +78,15 @@ public function save(array $form, array &$form_state) { watchdog('custom_block', 'Custom block type %label has been added.', array('%label' => $block_type->label()), WATCHDOG_NOTICE, l(t('Edit'), $uri['path'] . '/edit')); } + if (module_exists('translation_entity')) { + $key = 'language_configuration'; + $translation_form_state = array( + 'translation_entity' => array('key' => $key), + 'language' => array($key => array('entity_type' => 'custom_block', 'bundle' => $block_type->id())), + 'values' => array($key => array('translation_entity' => $form_state['values']['translation_entity'])), + ); + translation_entity_language_configuration_element_submit($form, $translation_form_state); + } $form_state['redirect'] = 'admin/structure/custom-blocks'; } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php index 7428aee..aaba53d 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php @@ -2,13 +2,13 @@ /** * @file - * Definition of Drupal\node\Plugin\Core\Entity\Node. + * Definition of Drupal\custom_block\Plugin\Core\Entity\CustomBlock. */ namespace Drupal\custom_block\Plugin\Core\Entity; use Drupal\Core\Entity\ContentEntityInterface; -use Drupal\Core\Entity\Entity; +use Drupal\Core\Entity\EntityNG; use Drupal\Core\Annotation\Plugin; use Drupal\Core\Annotation\Translation; @@ -29,6 +29,7 @@ * base_table = "block_custom", * revision_table = "block_custom_revision", * uri_callback = "custom_block_uri", + * menu_base_path = "block/%custom_block_machine_name", * fieldable = TRUE, * entity_keys = { * "id" = "bid", @@ -48,19 +49,19 @@ * } * ) */ -class CustomBlock extends Entity implements ContentEntityInterface { +class CustomBlock extends EntityNG implements ContentEntityInterface { /** * The block ID. * - * @var integer + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $bid; /** * The block revision ID. * - * @var integer + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $vid; @@ -71,54 +72,51 @@ class CustomBlock extends Entity implements ContentEntityInterface { * has been specified. Only default revisions are saved to the block_custom * table. * - * @var boolean + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $isDefaultRevision = TRUE; /** * The block UUID. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $uuid; /** * The custom block type (bundle). * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $type; /** * The custom block machine name. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $machine_name; /** * The block language code. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $langcode = LANGUAGE_NOT_SPECIFIED; /** * The block description. * - * @var string + * @var \Drupal\Core\Entity\Field\FieldInterface */ public $info; /** - * The block translation set ID. + * The block revision log message. * - * Translations sets are based on the ID of the block containing the source - * text for the translation set. - * - * @var integer + * @var \Drupal\Core\Entity\Field\FieldInterface */ - public $tbid; + public $log; /** * The theme the block is being created in. @@ -132,33 +130,24 @@ class CustomBlock extends Entity implements ContentEntityInterface { protected $theme; /** - * The block translation status. - * - * If the translation page needs to be updated, the value is 1; otherwise 0. - * - * @var integer - */ - public $translate; - - /** * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { - return $this->bid; + return $this->bid->value; } /** * Implements Drupal\Core\Entity\EntityInterface::bundle(). */ public function bundle() { - return $this->type; + return $this->type->value; } /** * Implements Drupal\Core\Entity\EntityInterface::label(). */ public function label($langcode = NULL) { - return $this->info; + return $this->info->value; } /** @@ -166,7 +155,9 @@ public function label($langcode = NULL) { */ public function createDuplicate() { $duplicate = parent::createDuplicate(); - $duplicate->vid = NULL; + $duplicate->set('vid', NULL); + $duplicate->set('bid', NULL); + $duplicate->set('machine_name', NULL); return $duplicate; } @@ -174,7 +165,7 @@ public function createDuplicate() { * Overrides Drupal\Core\Entity\Entity::getRevisionId(). */ public function getRevisionId() { - return $this->vid; + return $this->vid->value; } /** @@ -204,4 +195,30 @@ public function setTheme($theme) { public function getTheme() { return $this->theme; } + + /** + * The plain data values of the contained properties. + * + * Define default values. + * + * @var array + */ + protected $values = array(); + + /** + * Initialize the object. Invoked upon construction and wake up. + */ + protected function init() { + parent::init(); + // We unset all defined properties, so magic getters apply. + unset($this->bid); + unset($this->info); + unset($this->vid); + unset($this->log); + unset($this->machine_name); + unset($this->uuid); + unset($this->langcode); + unset($this->type); + unset($this->new); + } } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php index 2c1f498..cce38b2 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Derivative/CustomBlock.php @@ -40,13 +40,13 @@ public function getDerivativeDefinition($derivative_id, array $base_plugin_defin * Retrieves custom block definitions from storage. */ public function getDerivativeDefinitions(array $base_plugin_definition) { - $results = db_query('SELECT * FROM {block_custom}'); - foreach ($results as $result) { - $this->derivatives[$result->machine_name] = $base_plugin_definition; - $this->derivatives[$result->machine_name]['settings'] = array( - 'info' => $result->info, + $custom_blocks = entity_load_multiple('custom_block', entity_query('custom_block')->execute()); + foreach ($custom_blocks as $custom_block) { + $this->derivatives[$custom_block->machine_name->value] = $base_plugin_definition; + $this->derivatives[$custom_block->machine_name->value]['settings'] = array( + 'info' => $custom_block->info->value, ) + $base_plugin_definition['settings']; - $this->derivatives[$result->machine_name]['subject'] = $result->info; + $this->derivatives[$custom_block->machine_name->value]['subject'] = $custom_block->info->value; } return $this->derivatives; } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlock.php index 7a7bc00..f472ff7 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlock.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/block/block/CustomBlock.php @@ -93,9 +93,9 @@ public function blockBuild() { } else { return array( - '#markup' => t('Block with name %name does not exist, please create it.', array( + '#markup' => t('Block with name %name does not exist. Add custom block.', array( '%name' => $block_id, - '!url' => 'block/add' + '!url' => url('block/add') )), '#access' => user_access('administer blocks') );