Commit d34434d8 authored by webchick's avatar webchick

Issue #2244885 by alexpott: Add method to count number of entities with a particular field.

parent 13c930f9
......@@ -438,6 +438,7 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
foreach ($fields as $field) {
if (!$field->deleted) {
\Drupal::entityManager()->getStorage($field->entity_type)->onFieldDelete($field);
$field->deleted = TRUE;
}
}
......@@ -656,36 +657,63 @@ public static function getReservedColumns() {
/**
* Determines whether a field has any data.
*
* @return
* @return bool
* TRUE if the field has data for any entity; FALSE otherwise.
*/
public function hasData() {
if ($this->getBundles()) {
$storage_details = $this->getSchema();
$columns = array_keys($storage_details['columns']);
$factory = \Drupal::service('entity.query');
// Entity Query throws an exception if there is no base table.
$entity_type = \Drupal::entityManager()->getDefinition($this->entity_type);
if (!$entity_type->getBaseTable()) {
return FALSE;
return $this->entityCount(TRUE);
}
/**
* Determines the number of entities that have field data.
*
* @param bool $as_bool
* (Optional) Optimises query for hasData(). Defaults to FALSE.
*
* @return bool|int
* The number of entities that have field data. If $as_bool parameter is
* TRUE then the value will either be TRUE or FALSE.
*/
public function entityCount($as_bool = FALSE) {
$count = 0;
$factory = \Drupal::service('entity.query');
$entity_type = \Drupal::entityManager()->getDefinition($this->entity_type);
// Entity Query throws an exception if there is no base table.
if ($entity_type->getBaseTable()) {
if ($this->deleted) {
$query = $factory->get($this->entity_type)
->condition('id:' . $this->uuid() . '.deleted', 1);
}
$query = $factory->get($this->entity_type);
$group = $query->orConditionGroup();
foreach ($columns as $column) {
$group->exists($this->name . '.' . $column);
elseif ($this->getBundles()) {
$storage_details = $this->getSchema();
$columns = array_keys($storage_details['columns']);
$query = $factory->get($this->entity_type);
$group = $query->orConditionGroup();
foreach ($columns as $column) {
$group->exists($this->name . '.' . $column);
}
$query = $query->condition($group);
}
$result = $query
->condition($group)
->count()
->accessCheck(FALSE)
->range(0, 1)
->execute();
if ($result) {
return TRUE;
if (isset($query)) {
$query
->count()
->accessCheck(FALSE);
// If we are performing the query just to check if the field has data
// limit the number of rows returned by the subquery.
if ($as_bool) {
$query->range(0, 1);
}
$count = $query->execute();
}
}
return FALSE;
if ($as_bool) {
return (bool) $count;
}
else {
return (int) $count;
}
}
/**
......
<?php
/**
* @file
* Contains \Drupal\field\Tests\FieldEntityCountTest.
*/
namespace Drupal\field\Tests;
use Drupal\Core\Entity\ContentEntityDatabaseStorage;
/**
* Tests entityCount() and hasData() methods on FieldConfig entity.
*
* @see \Drupal\field\Entity\FieldConfig::entityCount()
* @see \Drupal\field\Entity\FieldConfig::hasData()
*/
class FieldEntityCountTest extends FieldUnitTestBase {
public static function getInfo() {
return array(
'name' => 'Field config entityCount() and hasData() tests.',
'description' => 'Tests entityCount() and hasData() methods on FieldConfig entity.',
'group' => 'Field API',
);
}
/**
* Tests entityCount() and hadData() methods.
*/
public function testEntityCountAndHasData() {
// Create a field with a cardinality of 2 to show that we are counting
// entities and not rows in a table.
/** @var \Drupal\field\Entity\FieldConfig $field */
$field = entity_create('field_config', array(
'name' => 'field_int',
'entity_type' => 'entity_test',
'type' => 'integer',
'cardinality' => 2,
));
$field->save();
entity_create('field_instance_config', array(
'entity_type' => 'entity_test',
'field_name' => 'field_int',
'bundle' => 'entity_test',
))->save();
$this->assertIdentical($field->hasdata(), FALSE, 'There are no entities with field data.');
$this->assertIdentical($field->entityCount(), 0, 'There are 0 entities with field data.');
// Create 1 entity without the field.
$entity = entity_create('entity_test');
$entity->name->value = $this->randomName();
$entity->save();
$this->assertIdentical($field->hasdata(), FALSE, 'There are no entities with field data.');
$this->assertIdentical($field->entityCount(), 0, 'There are 0 entities with field data.');
// Create 12 entities to ensure that the purging works as expected.
for ($i=0; $i < 12; $i++) {
$entity = entity_create('entity_test');
$value = mt_rand(1,99);
$value2 = mt_rand(1,99);
$entity->field_int[0]->value = $value;
$entity->field_int[1]->value = $value2;
$entity->name->value = $this->randomName();
$entity->save();
}
$storage = \Drupal::entityManager()->getStorage('entity_test');
if ($storage instanceof ContentEntityDatabaseStorage) {
// Count the actual number of rows in the field table.
$field_table_name = $storage->_fieldTableName($field);
$result = db_select($field_table_name, 't')
->fields('t')
->countQuery()
->execute()
->fetchField();
$this->assertEqual($result, 24, 'The field table has 24 rows.');
}
$this->assertIdentical($field->hasdata(), TRUE, 'There are entities with field data.');
$this->assertEqual($field->entityCount(), 12, 'There are 12 entities with field data.');
// Ensure the methods work on deleted fields.
$field->delete();
$this->assertIdentical($field->hasdata(), TRUE, 'There are entities with deleted field data.');
$this->assertEqual($field->entityCount(), 12, 'There are 12 entities with deleted field data.');
field_purge_batch(6);
$this->assertIdentical($field->hasdata(), TRUE, 'There are entities with deleted field data.');
$this->assertEqual($field->entityCount(), 6, 'There are 6 entities with deleted field data.');
}
}
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