Commit 6cab3d80 authored by slasher13's avatar slasher13 Committed by borisson_

Issue #2722783 by borisson_, marthinal, slasher13, generalconsensus: Deleting...

Issue #2722783 by borisson_, marthinal, slasher13, generalconsensus: Deleting a facet source leads to a fatal error on trying to edit facets associated with that facet source
parent 47144315
......@@ -2,9 +2,7 @@
namespace Drupal\core_search_facets\Plugin\facets\facet_source;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\core_search_facets\Plugin\CoreSearchFacetSourceInterface;
use Drupal\facets\FacetInterface;
use Drupal\facets\FacetSource\FacetSourcePluginBase;
......@@ -26,9 +24,6 @@ use Symfony\Component\HttpFoundation\RequestStack;
*/
class CoreNodeSearchFacetSource extends FacetSourcePluginBase implements CoreSearchFacetSourceInterface {
use DependencySerializationTrait;
use StringTranslationTrait;
/**
* The entity manager.
*
......@@ -332,4 +327,11 @@ class CoreNodeSearchFacetSource extends FacetSourcePluginBase implements CoreSea
return FALSE;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
return ['module' => ['node', 'search']];
}
}
......@@ -6,7 +6,9 @@
*/
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\facets\Entity\FacetSource;
use Drupal\search_api\Query\QueryInterface;
use Drupal\views\Entity\View;
/**
* Implements hook_help().
......@@ -40,3 +42,54 @@ function facets_search_api_query_alter(QueryInterface &$query) {
$facet_manager->alterQuery($query, $search_id);
}
}
/**
* Implements hook_entity_presave().
*
* We implement this to make sure that a facet gets removed on view updates, so
* we don't get broken facet blocks.
*/
function facets_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
// Make sure that we only react on view entities with changed displays.
if ($entity instanceof View && !empty($entity->original)) {
if ($entity->original->get('display') != $entity->get('display')) {
/** @var \Drupal\facets\FacetSource\FacetSourcePluginManager $facet_source_plugin_manager */
$facet_source_plugin_manager = \Drupal::getContainer()
->get('plugin.manager.facets.facet_source');
$definitions = $facet_source_plugin_manager->getDefinitions();
// Setup an array of sources that are deleted.
$sources = [];
foreach ($entity->original->get('display') as $k => $display) {
// Check if the current display is also a facet source plugin and that
// is removed from the view.
$test = 'search_api_views:' . $entity->id() . ':' . $display['id'];
if (array_key_exists($test, $definitions) && !array_key_exists($k, $entity->get('display'))) {
$entity_id = str_replace(':', '__', $test);
$source_entity = FacetSource::load($entity_id);
if (!is_null($source_entity)) {
$source_entity->delete();
$sources[] = $test;
}
}
}
// Loop over all deleted sources and delete the facets that were linked to
// that source.
if (count($sources) > 0) {
/** @var \Drupal\facets\FacetManager\DefaultFacetManager $fm */
$fm = \Drupal::getContainer()->get('facets.manager');
foreach ($sources as $source) {
$facets = $fm->getFacetsByFacetSourceId($source);
foreach ($facets as $facet) {
$facet->delete();
}
}
}
$facet_source_plugin_manager->clearCachedDefinitions();
}
}
}
......@@ -739,4 +739,17 @@ class Facet extends ConfigEntityBase implements FacetInterface {
return $this;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
parent::calculateDependencies();
$facet_dependencies = $this->getFacetSource()->calculateDependencies();
if (!empty($facet_dependencies)) {
$this->addDependencies($facet_dependencies);
}
return $this;
}
}
......@@ -166,7 +166,7 @@ class DefaultFacetManager {
* @return \Drupal\facets\FacetInterface[]
* An array of enabled facets.
*/
protected function getFacetsByFacetSourceId($facetsource_id) {
public function getFacetsByFacetSourceId($facetsource_id) {
$facets = [];
foreach ($this->facets as $facet) {
if ($facet->getFacetSourceId() == $facetsource_id) {
......
......@@ -2,7 +2,7 @@
namespace Drupal\facets\FacetSource;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Facets\FacetInterface;
......
......@@ -2,6 +2,7 @@
namespace Drupal\facets\FacetSource;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\facets\FacetInterface;
......@@ -14,7 +15,7 @@ use Drupal\facets\FacetInterface;
*
* @see plugin_api
*/
interface FacetSourcePluginInterface extends PluginFormInterface {
interface FacetSourcePluginInterface extends PluginFormInterface, DependentPluginInterface {
/**
* Fills the facet entities with results from the facet source.
......
......@@ -3,7 +3,6 @@
namespace Drupal\facets\Plugin\facets\facet_source;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\facets\Exception\InvalidQueryTypeException;
use Drupal\facets\FacetInterface;
use Drupal\search_api\Backend\BackendInterface;
......@@ -16,8 +15,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
use StringTranslationTrait;
/**
* The search index.
*
......
......@@ -2,7 +2,6 @@
namespace Drupal\facets\Plugin\facets\facet_source;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\facets\FacetSource\SearchApiFacetSourceInterface;
use Drupal\search_api\Plugin\views\query\SearchApiQuery;
use Drupal\search_api\Query\ResultSetInterface;
......@@ -22,8 +21,6 @@ use Drupal\views\Views;
*/
class SearchApiViews extends SearchApiBaseFacetSource implements SearchApiFacetSourceInterface {
use DependencySerializationTrait;
/**
* The entity manager.
*
......@@ -165,4 +162,14 @@ class SearchApiViews extends SearchApiBaseFacetSource implements SearchApiFacetS
return $this->index;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$plugin_id_array = explode(':', $this->pluginId);
$dependencies['config'] = ['views.view.' . $plugin_id_array[1]];
return $dependencies;
}
}
......@@ -4,6 +4,7 @@ namespace Drupal\facets\Tests;
use Drupal\Core\Url;
use Drupal\facets\Entity\Facet;
use Drupal\views\Entity\View;
/**
* Tests the overall functionality of the Facets admin UI.
......@@ -12,6 +13,8 @@ use Drupal\facets\Entity\Facet;
*/
class IntegrationTest extends WebTestBase {
public static $modules = ['views_ui'];
/**
* {@inheritdoc}
*/
......@@ -519,6 +522,76 @@ class IntegrationTest extends WebTestBase {
$this->assertText('item (1)');
}
/**
* Tests what happens when a dependency is removed.
*/
public function testOnViewRemoval() {
$id = "owl";
$name = "Owl";
$this->createFacet($name, $id);
$this->drupalGet('/admin/config/search/facets');
$this->assertResponse(200);
// Check that the expected facet sources and the owl facet are shown.
$this->assertText('search_api_views:search_api_test_view:block_1');
$this->assertText('search_api_views:search_api_test_view:page_1');
$this->assertText($name);
// Delete the view on which both facet sources are based.
$view = View::load('search_api_test_view');
$view->delete();
// Go back to the overview, make sure that the page doesn't show any errors
// and the facet/facet source are deleted.
$this->drupalGet('/admin/config/search/facets');
$this->assertResponse(200);
$this->assertNoText('search_api_views:search_api_test_view:page_1');
$this->assertNoText('search_api_views:search_api_test_view:block_1');
$this->assertNoText($name);
}
/**
* Tests what happens when a dependency is removed.
*/
public function testOnViewDisplayRemoval() {
$admin_user = $this->drupalCreateUser([
'administer search_api',
'administer facets',
'access administration pages',
'administer nodes',
'access content overview',
'administer content types',
'administer blocks',
'administer views',
]);
$this->drupalLogin($admin_user);
$id = "owl";
$name = "Owl";
$this->createFacet($name, $id);
$this->drupalGet('/admin/config/search/facets');
$this->assertResponse(200);
// Check that the expected facet sources and the owl facet are shown.
$this->assertText('search_api_views:search_api_test_view:block_1');
$this->assertText('search_api_views:search_api_test_view:page_1');
$this->assertText($name);
// Delete the view display for the page.
$this->drupalGet('admin/structure/views/view/search_api_test_view');
$this->drupalPostForm(NULL, [], $this->t('Delete Page'));
$this->drupalPostForm(NULL, [], $this->t('Save'));
// Go back to the overview, make sure that the page doesn't show any errors
// and the facet/facet source are deleted.
$this->drupalGet('/admin/config/search/facets');
$this->assertResponse(200);
$this->assertNoText('search_api_views:search_api_test_view:page_1');
$this->assertText('search_api_views:search_api_test_view:block_1');
$this->assertNoText($name);
}
/**
* Configures empty behavior option to show a text on empty results.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment