diff --git a/core/modules/node/config/views.view.content.yml b/core/modules/node/config/views.view.content.yml
index 39f6d60..487b04b 100644
--- a/core/modules/node/config/views.view.content.yml
+++ b/core/modules/node/config/views.view.content.yml
@@ -279,6 +279,7 @@ display:
text: Translate
optional: '1'
plugin_id: content_translation_link
+ provider: content_translation
dropbutton:
id: dropbutton
table: views
diff --git a/core/modules/views/lib/Drupal/views/Plugin/ViewsHandlerManager.php b/core/modules/views/lib/Drupal/views/Plugin/ViewsHandlerManager.php
index 4ac2fac..0a1fb76 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/ViewsHandlerManager.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/ViewsHandlerManager.php
@@ -77,7 +77,7 @@ public function __construct($handler_type, \Traversable $namespaces, ViewsData $
public function getHandler($item, $override = NULL) {
$table = $item['table'];
$field = $item['field'];
- $optional = isset($item['optional']) ? $item['optional'] : FALSE;
+ $optional = !empty($item['optional']);
// Get the plugin manager for this type.
$data = $this->viewsData->get($table);
@@ -118,7 +118,7 @@ public function getHandler($item, $override = NULL) {
}
// Finally, use the 'broken' handler.
- return $this->createInstance('broken');
+ return $this->createInstance('broken', array('optional' => $optional, 'original_configuration' => $item));
}
}
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php
index 58a7e53..76805c4 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php
@@ -77,11 +77,19 @@
public $relationship = NULL;
/**
+ * Whether or not this handler is optional.
+ *
+ * @var bool
+ */
+ protected $optional = FALSE;
+
+ /**
* Constructs a Handler object.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->is_handler = TRUE;
+ $this->optional = !empty($configuration['optional']);
}
/**
@@ -156,6 +164,15 @@ protected function defineOptions() {
}
/**
+ * Returns whether this handler is optional.
+ *
+ * @return bool
+ */
+ public function isOptional() {
+ return $this->optional;
+ }
+
+ /**
* Return a string representing this handler's name in the UI.
*/
public function adminLabel($short = FALSE) {
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/Broken.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/Broken.php
index 64a63a0..50cfb87 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/area/Broken.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/Broken.php
@@ -8,6 +8,7 @@
namespace Drupal\views\Plugin\views\area;
use Drupal\Component\Annotation\PluginID;
+use Drupal\views\ViewExecutable;
/**
* A special handler to take the place of missing or broken handlers.
@@ -19,7 +20,10 @@
class Broken extends AreaPluginBase {
public function adminLabel($short = FALSE) {
- return t('Broken/missing handler');
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ );
+ return $this->isOptional() ? t('Optional handler is missing (Module: @module) …', $args) : t('Broken/missing handler (Module: @module) …', $args);
}
public function defineOptions() { return array(); }
@@ -33,9 +37,32 @@ public function render($empty = FALSE) {
return array();
}
public function buildOptionsForm(&$form, &$form_state) {
- $form['markup'] = array(
- '#markup' => '
' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '
',
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ '@table' => $this->definition['original_configuration']['table'],
+ '@field' => $this->definition['original_configuration']['field'],
);
+
+ if ($this->isOptional()) {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is optional. The following handler is optional:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module will may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
+ else {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is broken or missing. The following handler is missing:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
}
/**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/argument/Broken.php b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Broken.php
index d74ab95..55c9c53 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/argument/Broken.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Broken.php
@@ -19,16 +19,42 @@
class Broken extends ArgumentPluginBase {
public function adminLabel($short = FALSE) {
- return t('Broken/missing handler');
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ );
+ return $this->isOptional() ? t('Optional handler is missing (Module: @module) …', $args) : t('Broken/missing handler (Module: @module) …', $args);
}
public function defineOptions() { return array(); }
public function ensureMyTable() { /* No table to ensure! */ }
public function query($group_by = FALSE) { /* No query to run */ }
public function buildOptionsForm(&$form, &$form_state) {
- $form['markup'] = array(
- '#markup' => '' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '
',
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ '@table' => $this->definition['original_configuration']['table'],
+ '@field' => $this->definition['original_configuration']['field'],
);
+
+ if ($this->isOptional()) {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is optional. The following handler is optional:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module will may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
+ else {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is broken or missing. The following handler is missing:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
}
/**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/field/Broken.php b/core/modules/views/lib/Drupal/views/Plugin/views/field/Broken.php
index 6310248..9afa63b 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/field/Broken.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/field/Broken.php
@@ -19,16 +19,42 @@
class Broken extends FieldPluginBase {
public function adminLabel($short = FALSE) {
- return t('Broken/missing handler');
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ );
+ return $this->isOptional() ? t('Optional handler is missing (Module: @module) …', $args) : t('Broken/missing handler (Module: @module) …', $args);
}
public function defineOptions() { return array(); }
public function ensureMyTable() { /* No table to ensure! */ }
public function query($group_by = FALSE) { /* No query to run */ }
public function buildOptionsForm(&$form, &$form_state) {
- $form['markup'] = array(
- '#markup' => '' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '
',
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ '@table' => $this->definition['original_configuration']['table'],
+ '@field' => $this->definition['original_configuration']['field'],
);
+
+ if ($this->isOptional()) {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is optional. The following handler is optional:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module will may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
+ else {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is broken or missing. The following handler is missing:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
}
/**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/filter/Broken.php b/core/modules/views/lib/Drupal/views/Plugin/views/filter/Broken.php
index 701cabb..23b9dab 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/filter/Broken.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/filter/Broken.php
@@ -27,16 +27,42 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
}
public function adminLabel($short = FALSE) {
- return t('Broken/missing handler');
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ );
+ return $this->isOptional() ? t('Optional handler is missing (Module: @module) …', $args) : t('Broken/missing handler (Module: @module) …', $args);
}
public function defineOptions() { return array(); }
public function ensureMyTable() { /* No table to ensure! */ }
public function query($group_by = FALSE) { /* No query to run */ }
public function buildOptionsForm(&$form, &$form_state) {
- $form['markup'] = array(
- '#markup' => '' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '
',
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ '@table' => $this->definition['original_configuration']['table'],
+ '@field' => $this->definition['original_configuration']['field'],
);
+
+ if ($this->isOptional()) {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is optional. The following handler is optional:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module will may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
+ else {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is broken or missing. The following handler is missing:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
}
/**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/relationship/Broken.php b/core/modules/views/lib/Drupal/views/Plugin/views/relationship/Broken.php
index c891f00..6312fec 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/relationship/Broken.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/relationship/Broken.php
@@ -19,16 +19,42 @@
class Broken extends RelationshipPluginBase {
public function adminLabel($short = FALSE) {
- return t('Broken/missing handler');
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ );
+ return $this->isOptional() ? t('Optional handler is missing (Module: @module) …', $args) : t('Broken/missing handler (Module: @module) …', $args);
}
public function defineOptions() { return array(); }
public function ensureMyTable() { /* No table to ensure! */ }
public function query() { /* No query to run */ }
public function buildOptionsForm(&$form, &$form_state) {
- $form['markup'] = array(
- '#markup' => '' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '
',
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ '@table' => $this->definition['original_configuration']['table'],
+ '@field' => $this->definition['original_configuration']['field'],
);
+
+ if ($this->isOptional()) {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is optional. The following handler is optional:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module will may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
+ else {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is broken or missing. The following handler is missing:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
}
/**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/sort/Broken.php b/core/modules/views/lib/Drupal/views/Plugin/views/sort/Broken.php
index 341bc8b..4bd460d 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/sort/Broken.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/sort/Broken.php
@@ -19,16 +19,42 @@
class Broken extends SortPluginBase {
public function adminLabel($short = FALSE) {
- return t('Broken/missing handler');
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ );
+ return $this->isOptional() ? t('Optional handler is missing (Module: @module) …', $args) : t('Broken/missing handler (Module: @module) …', $args);
}
public function defineOptions() { return array(); }
public function ensureMyTable() { /* No table to ensure! */ }
public function query($group_by = FALSE) { /* No query to run */ }
public function buildOptionsForm(&$form, &$form_state) {
- $form['markup'] = array(
- '#markup' => '' . t('The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.') . '
',
+ $args = array(
+ '@module' => $this->definition['original_configuration']['provider'],
+ '@table' => $this->definition['original_configuration']['table'],
+ '@field' => $this->definition['original_configuration']['field'],
);
+
+ if ($this->isOptional()) {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is optional. The following handler is optional:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module will may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
+ else {
+ $form['markup'] = array(
+ '#markup' => '' . t('The handler for this item is broken or missing. The following handler is missing:
+- Module: @module
+- Table: @table
+- Field: @field
+
+Enabling the appropriate module may solve this issue. Otherwise try to look whether there is a module update available.', $args) . '
',
+ );
+ }
}
/**
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_broken.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_broken.yml
new file mode 100644
index 0000000..e5870e5
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_broken.yml
@@ -0,0 +1,89 @@
+base_table: views_test_data
+core: '8'
+description: ''
+status: '1'
+display:
+ default:
+ display_options:
+ defaults:
+ fields: '0'
+ pager: '0'
+ pager_options: '0'
+ sorts: '0'
+ fields:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ filters:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ arguments:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ sorts:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ order: ASC
+ provider: views
+ relationships:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ header:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ footer:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ empty:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ provider: views
+ pager:
+ options:
+ offset: '0'
+ type: none
+ pager_options: { }
+ display_plugin: default
+ display_title: Master
+ id: default
+ position: '0'
+label: 'Test view'
+id: test_view_broken
+tag: ''
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_optional.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_optional.yml
new file mode 100644
index 0000000..7068998
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_optional.yml
@@ -0,0 +1,97 @@
+base_table: views_test_data
+core: '8'
+description: ''
+status: '1'
+display:
+ default:
+ display_options:
+ defaults:
+ fields: '0'
+ pager: '0'
+ pager_options: '0'
+ sorts: '0'
+ fields:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ filters:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ arguments:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ sorts:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ order: ASC
+ optional: 1
+ provider: views
+ relationships:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ header:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ footer:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ empty:
+ id_broken:
+ field: id_broken
+ id: id_broken
+ relationship: none
+ table: views_test_data
+ plugin_id: numeric
+ optional: 1
+ provider: views
+ pager:
+ options:
+ offset: '0'
+ type: none
+ pager_options: { }
+ display_plugin: default
+ display_title: Master
+ id: default
+ position: '0'
+label: 'Test view'
+id: test_view_optional
+tag: ''
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php
index 1125b2f..5d10958 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php
@@ -102,11 +102,12 @@ public function buildForm(array $form, array &$form_state) {
// If this relationship is valid for this type, add it to the list.
$data = Views::viewsData()->get($relationship['table']);
- $base = $data[$relationship['field']]['relationship']['base'];
- $base_fields = Views::viewsDataHelper()->fetchFields($base, $form_state['type'], $executable->display_handler->useGroupBy());
- if (isset($base_fields[$item['table'] . '.' . $item['field']])) {
- $relationship_handler->init($executable, $executable->display_handler, $relationship);
- $relationship_options[$relationship['id']] = $relationship_handler->adminLabel();
+ if (isset($data[$relationship['field']]['relationship']['base']) && $base = $data[$relationship['field']]['relationship']['base']) {
+ $base_fields = Views::viewsDataHelper()->fetchFields($base, $form_state['type'], $executable->display_handler->useGroupBy());
+ if (isset($base_fields[$item['table'] . '.' . $item['field']])) {
+ $relationship_handler->init($executable, $executable->display_handler, $relationship);
+ $relationship_options[$relationship['id']] = $relationship_handler->adminLabel();
+ }
}
}
@@ -142,8 +143,6 @@ public function buildForm(array $form, array &$form_state) {
);
}
- $form['#title'] = t('Configure @type: @item', array('@type' => $types[$type]['lstitle'], '@item' => $handler->adminLabel()));
-
if (!empty($handler->definition['help'])) {
$form['options']['form_description'] = array(
'#markup' => $handler->definition['help'],
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/HandlerTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/HandlerTest.php
index f331257..dca09c3 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/HandlerTest.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/HandlerTest.php
@@ -7,6 +7,7 @@
namespace Drupal\views_ui\Tests;
+use Drupal\Component\Utility\String;
use Drupal\views\ViewExecutable;
/**
@@ -21,7 +22,7 @@ class HandlerTest extends UITestBase {
*
* @var array
*/
- public static $testViews = array('test_view_empty');
+ public static $testViews = array('test_view_empty', 'test_view_broken', 'test_view_optional');
public static function getInfo() {
return array(
@@ -73,7 +74,7 @@ protected function viewsData() {
/**
* Tests UI CRUD.
*/
- public function testUICRUD() {
+ public function ptestUICRUD() {
$handler_types = ViewExecutable::viewsHandlerTypes();
foreach ($handler_types as $type => $type_info) {
// Test adding handlers.
@@ -143,4 +144,55 @@ public function testUICRUD() {
$this->assertTrue(isset($display['display_options'][$type_info['plural']][$id]), 'Ensure the field was added to the view itself.');
}
+ /**
+ * Test broken handlers.
+ */
+ public function testBrokenHandlers() {
+ $this->drupalGet('admin/structure/views/view/test_view_broken/edit');
+
+ $handler_types = ViewExecutable::viewsHandlerTypes();
+ foreach ($handler_types as $type => $type_info) {
+ $href = "admin/structure/views/nojs/config-item/test_view_broken/default/$type/id_broken";
+
+ $result = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href));
+ $this->assertEqual(count($result), 1, String::format('Handler (%type) edit link found.', array('%type' => $type)));
+ $args = array(
+ '@module' => 'views',
+ '@table' => 'views_test_data',
+ '@field' => 'id_broken',
+ );
+
+ $this->assertTrue(strpos((string) $result[0], t('Broken/missing handler (Module: @module) …', $args)) !== FALSE, 'Ensure the broken handler text was found.');
+
+ $this->drupalGet($href);
+ $result = $this->xpath('//h1');
+ $this->assertTrue(strpos((string) $result[0], t('Broken/missing handler (Module: @module, Table: @table, Field: @field)', $args)) !== FALSE, 'Ensure the broken handler text was found.');
+ }
+ }
+
+ /**
+ * Test optional handlers.
+ */
+ public function testOptionalHandlers() {
+ $this->drupalGet('admin/structure/views/view/test_view_optional/edit');
+
+ $handler_types = ViewExecutable::viewsHandlerTypes();
+ foreach ($handler_types as $type => $type_info) {
+ $href = "admin/structure/views/nojs/config-item/test_view_optional/default/$type/id_broken";
+ $result = $this->xpath('//a[contains(@href, :href)]', array(':href' => $href));
+ $this->assertEqual(count($result), 1, String::format('Handler (%type) edit link found.', array('%type' => $type)));
+ $args = array(
+ '@module' => 'views',
+ '@table' => 'views_test_data',
+ '@field' => 'id_broken',
+ );
+
+ $this->assertTrue(strpos((string) $result[0], t('Optional handler is missing (Module: @module) …', $args)) !== FALSE, 'Ensure the optional handler text was found.');
+
+ $this->drupalGet($href);
+ $result = $this->xpath('//h1');
+ $this->assertTrue(strpos((string) $result[0], t('Broken/missing handler (Module: @module, Table: @table, Field: @field)', $args)) !== FALSE, 'Ensure the broken handler text was found.');
+ }
+ }
+
}