sparql_entity_storage-8.x-1.0-alpha8/tests/src/Kernel/SparqlEntityQueryTest.php

tests/src/Kernel/SparqlEntityQueryTest.php
<?php

declare(strict_types=1);

namespace Drupal\Tests\sparql_entity_storage\Kernel;

use Drupal\sparql_entity_storage\Entity\Query\Sparql\SparqlQueryInterface;
use Drupal\sparql_entity_storage\Exception\SparqlQueryException;
use Drupal\sparql_entity_storage\Exception\UnsupportedCharactersException;
use Drupal\sparql_test\Entity\TestSparql;

/**
 * Tests entity query functionality of the SPARQL backend.
 *
 * @see \Drupal\KernelTests\Core\Entity\EntityQueryTest
 *
 * @group sparql_entity_storage
 */
class SparqlEntityQueryTest extends SparqlKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'datetime',
    'sparql_field_test',
  ];

  /**
   * A list of query results.
   *
   * @var array|null
   */
  protected ?array $results;

  /**
   * Dummy reference entities.
   *
   * @var \Drupal\sparql_test\Entity\TestSparql[]|null
   */
  protected ?array $entities;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->installConfig(['sparql_field_test']);

    // Create 10 referable entities.
    $prefix = "http://fruit.example.com/";
    for ($i = 0; $i < 10; $i++) {
      $id = sprintf("%s%03d", $prefix, $i + 1);
      $entity = TestSparql::create([
        'id' => $id,
        'title' => 'fruit title ' . ($i + 1),
        'type' => 'fruit',
        'text' => 'text field ' . ($i % 2),
      ]);
      $entity->save();
      $this->entities[$i] = $entity;
    }

    $prefix = "http://vegetable.example.com/";
    foreach ($this->getTestEntityValues() as $i => $values) {
      $id = sprintf("%s%03d", $prefix, $i + 1);
      $values += [
        'id' => $id,
        'type' => 'vegetable',
      ];
      TestSparql::create($values)->save();
    }
  }

  /**
   * Tests that the case field_ref.entity is handled.
   */
  public function testEntityColumns(): void {
    $ids = array_keys($this->getQuery()
      ->condition('reference.entity', $this->entities[1]->id())
      ->execute());
    $this->assertSame([
      'http://vegetable.example.com/004',
      'http://vegetable.example.com/009',
    ], $ids);
  }

  /**
   * Tests basic functionality related to Id and bundle filtering.
   */
  public function testIdBundleFilters() {
    // Test an invalid bundle filter.
    $this->results = $this->getQuery()
      ->condition('type', 'invalid')
      ->execute();
    $this->assertResult();

    // Checks the '=' operator for IDs for a valid ID and a valid bundle.
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/001')
      ->condition('type', 'vegetable')
      ->execute();
    $this->assertResult('http://vegetable.example.com/001');

    // Checks the '=' operator for IDs for a valid ID and a different bundle.
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/001')
      ->condition('type', 'fruit')
      ->execute();
    $this->assertResult();

    // Checks the '!=' operator for the bundle.
    $this->results = $this->getQuery()
      ->condition('id', [
        'http://vegetable.example.com/001',
        'http://fruit.example.com/002',
      ], 'IN')
      ->condition('type', 'vegetable', '!=')
      ->execute();
    $this->assertResult('http://fruit.example.com/002');

    // Checks the IN operator for the bundle.
    $this->results = $this->getQuery()
      ->condition('id', [
        'http://fruit.example.com/002',
        'http://vegetable.example.com/001',
      ], 'IN')
      ->condition('type', ['fruit', 'vegetable'], 'IN')
      ->sort('id')
      ->execute();
    $this->assertResult('http://fruit.example.com/002', 'http://vegetable.example.com/001');

    // Checks the NOT IN operator for the bundle.
    $this->results = $this->getQuery()
      ->condition('id', [
        'http://vegetable.example.com/001',
        'http://fruit.example.com/002',
      ], 'IN')
      ->condition('type', ['vegetable'], 'NOT IN')
      ->execute();
    $this->assertResult('http://fruit.example.com/002');

    // Checks the 'IN' operator for IDs.
    $this->results = $this->getQuery()
      ->condition('id', [
        'http://vegetable.example.com/000',
        'http://vegetable.example.com/001',
        'http://vegetable.example.com/002',
      ], 'IN')
      ->condition('type', 'vegetable')
      ->execute();
    $this->assertResult('http://vegetable.example.com/001', 'http://vegetable.example.com/002');

    // Checks the '=' operator for IDs for an invalid ID.
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/000')
      ->condition('type', 'vegetable')
      ->execute();
    $this->assertResult();

    // Checks the '!=' operator for IDs for a valid ID.
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/001', '!=')
      ->condition('type', 'vegetable')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002', 'http://vegetable.example.com/003', 'http://vegetable.example.com/004', 'http://vegetable.example.com/005', 'http://vegetable.example.com/006', 'http://vegetable.example.com/007', 'http://vegetable.example.com/008', 'http://vegetable.example.com/009', 'http://vegetable.example.com/010');

    // Checks the 'NOT IN' operator for IDs for a valid ID.
    $this->results = $this->getQuery()
      ->condition('id', [
        'http://vegetable.example.com/002',
        'http://vegetable.example.com/003',
        'http://vegetable.example.com/004',
        'http://vegetable.example.com/005',
        'http://vegetable.example.com/006',
        'http://vegetable.example.com/007',
        'http://vegetable.example.com/008',
        'http://vegetable.example.com/009',
        'http://vegetable.example.com/010',
      ], 'NOT IN')
      ->condition('type', 'vegetable')
      ->execute();
    $this->assertResult('http://vegetable.example.com/001');

    // Try to fetch a NULL ID.
    $this->expectException(\Exception::class);
    $this->expectExceptionMessage('The value cannot be NULL for conditions related to the Id and bundle keys.');
    $this->results = $this->getQuery()
      ->condition('id', NULL)
      ->condition('type', 'vegetable')
      ->execute();

    // Try to filter ID with an invalid operator.
    $this->expectException(\Exception::class);
    $this->expectExceptionMessage("Only '=', '!=', '<>', 'IN', 'NOT IN' operators are allowed for the Id and bundle keys.");
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/003', 'LIKE')
      ->condition('type', 'vegetable')
      ->execute();

    // Try to fetch a NULL bundle.
    $this->expectException(\Exception::class);
    $this->expectExceptionMessage('The value cannot be NULL for conditions related to the Id and bundle keys.');
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/002')
      ->condition('type', NULL)
      ->execute();

    // Try to filter bundle with an invalid operator.
    $this->expectException(\Exception::class);
    $this->expectExceptionMessage("Only '=', '!=', '<>', 'IN', 'NOT IN' operators are allowed for the Id and bundle keys.");
    $this->results = $this->getQuery()
      ->condition('id', 'http://vegetable.example.com/003')
      ->condition('type', 'multi', 'STARTS WITH')
      ->execute();
  }

  /**
   * Tests basic functionality.
   *
   * The queries here are very simple only to ensure proper functionality of the
   * basic conditions.
   */
  public function testBaseEntityQueryFilters() {
    // Submit an empty query.
    $this->results = $this->getQuery()
      ->sort('id')
      ->execute();
    $this->assertCount(20, $this->results);

    // Submit an empty 'OR' query.
    $this->results = $this->getQuery('OR')
      ->sort('id')
      ->execute();
    $this->assertCount(20, $this->results);

    $this->results = $this->getQuery()
      ->exists('field_text')
      ->condition("text.format", 'plain_text')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/001');

    $this->results = $this->getQuery()
      ->exists("text.format")
      ->condition('text', '<body>', 'LIKE')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002');

    $this->results = $this->getQuery()
      ->condition('text', '<p>', 'CONTAINS')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002');

    $this->results = $this->getQuery()
      ->condition('text', '<html>', 'STARTS WITH')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002');

    $this->results = $this->getQuery()
      ->condition('text', '</html>', 'ENDS WITH')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002');

    $this->results = $this->getQuery()
      ->condition('text', '</html>', 'ENDS WITH')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002');

    $this->results = $this->getQuery()
      ->condition('reference', $this->entities[6]->id())
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/004', 'http://vegetable.example.com/010');

    $this->results = $this->getQuery()
      ->exists('text.format')
      ->notExists('date')
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/002');

    // OR conjunctions.
    $this->results = $this->getQuery('OR')
      ->exists('text.format')
      ->condition('reference', $this->entities[6]->id())
      ->sort('id')
      ->execute();
    $this->assertResult('http://vegetable.example.com/001', 'http://vegetable.example.com/002', 'http://vegetable.example.com/004', 'http://vegetable.example.com/010');
  }

  /**
   * Tests more complex functionality.
   */
  public function testNestedConditionGroups() {
    $query = $this->getQuery('OR');

    // Entity 001 should match.
    $condition = $query->andConditionGroup();
    $condition->exists('text.format');
    $condition->condition('text.value', 'test', 'CONTAINS');
    $condition->condition('text.format', ['plain_text', 'filtered_html'], 'IN');
    $query->condition($condition);

    // Entity 002 should match.
    $condition = $query->orConditionGroup();
    $condition->condition('text', '<html', 'STARTS WITH');
    $condition->condition('text.value', '/html>', 'ENDS WITH');

    // Entity 006 should match.
    $subcondition = $query->andConditionGroup();
    $subcondition->condition('text_multi', 'test text multi 1');
    $subcondition->condition('text_multi', 'sample string 2', 'CONTAINS');
    $condition->condition($subcondition);

    // Entity 004 should match.
    $subcondition = $query->andConditionGroup();
    $subcondition->condition('reference', $this->entities[4]->id());
    $subcondition->notExists('date');
    $condition->condition($subcondition);
    $query->condition($condition);

    $this->results = $query->sort('id')->execute();
    $this->assertResult('http://vegetable.example.com/001', 'http://vegetable.example.com/002', 'http://vegetable.example.com/004', 'http://vegetable.example.com/006');
  }

  /**
   * Tests sorting and order mechanisms.
   */
  public function testSortOrder() {
    // Sort without direction. Defaults to ASC.
    $this->results = $this->getQuery()
      ->condition('type', 'fruit')
      ->sort('text')
      ->execute();
    $this->assertResult('http://fruit.example.com/001', 'http://fruit.example.com/003', 'http://fruit.example.com/005', 'http://fruit.example.com/007', 'http://fruit.example.com/009', 'http://fruit.example.com/002', 'http://fruit.example.com/004', 'http://fruit.example.com/006', 'http://fruit.example.com/008', 'http://fruit.example.com/010');

    // Sort by ascending direction.
    $this->results = $this->getQuery()
      ->condition('type', 'fruit')
      ->sort('text', 'ASC')
      ->execute();
    $this->assertResult('http://fruit.example.com/001', 'http://fruit.example.com/003', 'http://fruit.example.com/005', 'http://fruit.example.com/007', 'http://fruit.example.com/009', 'http://fruit.example.com/002', 'http://fruit.example.com/004', 'http://fruit.example.com/006', 'http://fruit.example.com/008', 'http://fruit.example.com/010');

    // Sort by descending direction.
    $this->results = $this->getQuery()
      ->condition('type', 'fruit')
      ->sort('text', 'DESC')
      ->execute();
    $this->assertResult('http://fruit.example.com/002', 'http://fruit.example.com/004', 'http://fruit.example.com/006', 'http://fruit.example.com/008', 'http://fruit.example.com/010', 'http://fruit.example.com/001', 'http://fruit.example.com/003', 'http://fruit.example.com/005', 'http://fruit.example.com/007', 'http://fruit.example.com/009');

    // Test multiple property ordering.
    $this->results = $this->getQuery()
      ->condition('type', 'fruit')
      ->sort('text', 'DESC')
      ->sort('id', 'DESC')
      ->execute();
    $this->assertResult('http://fruit.example.com/010', 'http://fruit.example.com/008', 'http://fruit.example.com/006', 'http://fruit.example.com/004', 'http://fruit.example.com/002', 'http://fruit.example.com/009', 'http://fruit.example.com/007', 'http://fruit.example.com/005', 'http://fruit.example.com/003', 'http://fruit.example.com/001');

    $this->results = $this->getQuery()
      ->condition('type', 'fruit')
      ->sort('text')
      ->sort('id', 'DESC')
      ->execute();
    $this->assertResult('http://fruit.example.com/009', 'http://fruit.example.com/007', 'http://fruit.example.com/005', 'http://fruit.example.com/003', 'http://fruit.example.com/001', 'http://fruit.example.com/010', 'http://fruit.example.com/008', 'http://fruit.example.com/006', 'http://fruit.example.com/004', 'http://fruit.example.com/002');

    // Test the bundle key as it is a separate special case along with the id.
    $sub_query = $this->getQuery()->orConditionGroup();
    $sub_query
      ->condition('id', 'http://fruit.example.com/009')
      ->condition('id', 'http://vegetable.example.com/003');

    $this->results = $this->getQuery()
      ->condition($sub_query)
      ->sort('type')
      ->execute();
    $this->assertResult('http://fruit.example.com/009', 'http://vegetable.example.com/003');

    $this->results = $this->getQuery()
      ->condition($sub_query)
      ->sort('type', 'DESC')
      ->execute();
    $this->assertResult('http://vegetable.example.com/003', 'http://fruit.example.com/009');

    // Test sorting using an OR query. Assert that mapping conditions are placed
    // individually.
    $this->results = $this->getQuery('OR')
      ->condition($sub_query)
      ->sort('type', 'DESC')
      ->execute();
    $this->assertResult('http://vegetable.example.com/003', 'http://fruit.example.com/009');

    // Invalid directions are not allowed.
    $this->expectException(\RuntimeException::class);
    $this->expectExceptionMessage('Only "ASC" and "DESC" are allowed as sort order.');
    $this->getQuery()->sort('id', 'SOME_INVALID_DIRECTION');
  }

  /**
   * Tests operators '<', '>', '<=', '>=' for Ids.
   *
   * @dataProvider idStringComparisonDataProvider
   */
  public function testIdStringComparison($value, $operator, $expected_results) {
    $query = $this->getQuery();
    $query->condition('id', $value, $operator);
    $this->results = $query->sort('id')->execute();
    $this->assertResult($expected_results);
  }

  /**
   * Data provider for testIdStringComparison test.
   */
  public static function idStringComparisonDataProvider(): array {
    return [
      [
        'http://fruit.example.com/002',
        '<',
        ['http://fruit.example.com/001'],
      ],
      [
        'http://fruit.example.com/002',
        '<=',
        ['http://fruit.example.com/001', 'http://fruit.example.com/002'],
      ],
      [
        'http://fruit.example.com/009',
        '>',
        // The vegetable bundle entities have an id starting with 'http://m'
        // which is sorted after the 'http://d' so all entities of the
        // vegetable bundled are also returned for the '>' and '>=' operators.
        [
          'http://fruit.example.com/010',
          'http://vegetable.example.com/001',
          'http://vegetable.example.com/002',
          'http://vegetable.example.com/003',
          'http://vegetable.example.com/004',
          'http://vegetable.example.com/005',
          'http://vegetable.example.com/006',
          'http://vegetable.example.com/007',
          'http://vegetable.example.com/008',
          'http://vegetable.example.com/009',
          'http://vegetable.example.com/010',
        ],
      ],
      [
        'http://fruit.example.com/009',
        '>=',
        [
          'http://fruit.example.com/009',
          'http://fruit.example.com/010',
          'http://vegetable.example.com/001',
          'http://vegetable.example.com/002',
          'http://vegetable.example.com/003',
          'http://vegetable.example.com/004',
          'http://vegetable.example.com/005',
          'http://vegetable.example.com/006',
          'http://vegetable.example.com/007',
          'http://vegetable.example.com/008',
          'http://vegetable.example.com/009',
          'http://vegetable.example.com/010',
        ],
      ],
    ];
  }

  /**
   * Tests the NOT EXISTS operator.
   */
  public function testNotExists(): void {
    $entity = TestSparql::create([
      'id' => 'http://fruit.example.com/not_exists',
      'title' => 'fruit title not exists',
      'type' => 'fruit',
    ]);
    $entity->save();
    $this->entities[] = $entity;

    $results = $this->getQuery()
      ->condition('type', 'fruit')
      ->notExists('text')
      ->execute();

    $this->assertCount(1, $results);
    $this->assertContains('http://fruit.example.com/not_exists', $results);
  }

  /**
   * Tests query with a double quote in the subject.
   */
  public function testQueryWithDoubleQuote(): void {
    // Queries are a bit more flexible. We do not need to block double quotes
    // as the structure of the query can be complex, the compilation does not
    // happen until later, and unlike the storage class load method, if we
    // simply remove the subject, we might end up returning all results. Same
    // will happen if the condition is an "if the subject is not a string" -
    // removing it will end up returning unexpected results. So, allowing an
    // exception to be thrown, shifts the responsibility to the user to use
    // custom query expressions to fetch the required results.
    $this->expectException(SparqlQueryException::class);
    $results = $this->getQuery()
      ->condition('id', 'some string with "double quotes"')
      ->execute();
    $this->assertCount(0, $results);
  }

  /**
   * Tests allowed characters and symbols in the subject.
   *
   * @param string $iri
   *   The IRI to test.
   * @param bool $supports
   *   Whether the IRI is supported.
   * @param string $unsupported_characters
   *   The unsupported characters in the IRI.
   *
   * @dataProvider saveWithSpecialCharactersDataProvider
   */
  public function testSaveWithSpecialCharacters(string $iri, bool $supports, string $unsupported_characters = ''): void {
    if (!$supports) {
      $this->expectException(UnsupportedCharactersException::class);
      $this->expectExceptionMessage("The entity ID '$iri' contains unsupported characters: $unsupported_characters");
    }

    $entity = TestSparql::create([
      'id' => $iri,
      'title' => $this->randomString(),
      'type' => 'fruit',
    ]);
    $entity->save();
    $this->assertSame($iri, $entity->id());
  }

  /**
   * Data provider for testSaveWithSpecialCharacters test.
   */
  public static function saveWithSpecialCharactersDataProvider(): array {
    return [
      [
        'http://example.com/greek-utf/παράδειγμα',
        FALSE,
        'π, α, ρ, ά, δ, ε, ι, γ, μ',
      ],
      ['http://example.com/some space', FALSE, '(space)'],
      ['http://example.com/{curly-brackets}', FALSE, '{, }'],
      ['http://example.com/[brackets]', TRUE],
      ['http://example.com/(parentheses)', TRUE],
      ['http://example.com/<angle-brackets>', FALSE, '<'],
      ['http://example.com/\\backslash', FALSE, '\\'],
      ['http://example.com/|pipe', FALSE, '|'],
      ['http://example.com/`backtick`', FALSE, '`'],
      ['http://example.com/!exclamation', TRUE],
      ['http://example.com/@at', TRUE],
      ['http://example.com/#hash', TRUE],
      ['http://example.com/$dollar', TRUE],
      ['http://example.com/%percent', TRUE],
      ['http://example.com/^caret', FALSE, '^'],
      ['http://example.com/&ampersand', TRUE],
      ['http://example.com/*asterisk', TRUE],
      ['http://example.com/-hyphen', TRUE],
      ['http://example.com/_underscore', TRUE],
      ['http://example.com/=equals', TRUE],
      ['http://example.com/+plus', TRUE],
      ['http://example.com/;semicolon', TRUE],
      ['http://example.com/:colon', TRUE],
      ['http://example.com/,comma', TRUE],
      ['http://example.com/.dot', TRUE],
      ['http://example.com/?question', TRUE],
      ['http://example.com/\'single-quote', TRUE],
      ['http://example.com/"double-quote', FALSE, '"'],
    ];
  }

  /**
   * Tests allowed characters and symbols in the subject during loading.
   *
   * @param string $iri
   *   The IRI to test.
   * @param string $unsupported_characters
   *   The unsupported characters in the IRI.
   *
   * @dataProvider loadWithSpecialCharactersDataProvider
   */
  public function testLoadWithSpecialCharactersDataProvider(string $iri, string $unsupported_characters = ''): void {
    $this->expectException(UnsupportedCharactersException::class);
    $this->expectExceptionMessage("The entity ID '$iri' contains unsupported characters: $unsupported_characters");
    \Drupal::entityTypeManager()->getStorage('sparql_test')->load($iri);
  }

  /**
   * Data provider for testLoadWithSpecialCharactersDataProvider test.
   */
  public static function loadWithSpecialCharactersDataProvider(): array {
    return [
      ['http://example.com/some space', '(space)'],
      ['http://example.com/{curly-brackets}', '{, }'],
      ['http://example.com/<angle-brackets>', '<'],
      ['http://example.com/\\backslash', '\\'],
      ['http://example.com/|pipe', '|'],
      ['http://example.com/`backtick`', '`'],
      ['http://example.com/^caret', '^'],
      ['http://example.com/"double-quote', '"'],
    ];
  }

  /**
   * Asserts that arrays are identical.
   */
  protected function assertResult(): void {
    $assert = [];
    $expected = func_get_args();
    if ($expected && is_array($expected[0])) {
      $expected = $expected[0];
    }
    foreach ($expected as $binary) {
      $assert[$binary] = strval($binary);
    }
    $this->assertSame($assert, $this->results);
  }

  /**
   * Provides entity values for the test's setup.
   *
   * @return array
   *   An array of entity values.
   */
  protected function getTestEntityValues(): array {
    $time = $this->container->get('datetime.time')->getRequestTime();
    $return = [];
    // Entity 001.
    $return[] = [
      'text' => [
        'value' => 'test text 1',
        'format' => 'plain_text',
      ],
      'text_multi' => [
        'test text multi 1',
      ],
      'date' => $time,
      'reference' => [
        $this->entities[4]->id(),
      ],
    ];

    // Entity 002.
    $return[] = [
      'text' => [
        'value' => '<html><body><p>Hello world!</p></body></html>',
        'format' => 'full_html',
      ],
      'text_multi' => [
        'test text multi 1',
      ],
    ];

    // Entity 003.
    $return[] = [
      'text' => 'test text 1',
      'text_multi' => [
        'test text multi 2',
      ],
      'date' => $time,
      'reference' => [
        $this->entities[2]->id(),
        $this->entities[3]->id(),
        $this->entities[4]->id(),
      ],
    ];

    // Entity 004.
    $return[] = [
      'reference' => [
        $this->entities[0]->id(),
        $this->entities[1]->id(),
        $this->entities[2]->id(),
        $this->entities[3]->id(),
        $this->entities[4]->id(),
        $this->entities[5]->id(),
        $this->entities[6]->id(),
        $this->entities[7]->id(),
        $this->entities[8]->id(),
        $this->entities[9]->id(),
      ],
    ];

    // Entity 005.
    $return[] = [
      'text' => 'sample string 2',
      'text_multi' => [
        'test text multi 1',
        'test text multi 3',
        'test text multi 2',
      ],
    ];

    // Entity 006.
    $return[] = [
      'text' => 'sample string 1',
      'text_multi' => [
        'test text multi 1',
        'sample string 2',
      ],
      'reference' => [
        $this->entities[8]->id(),
        $this->entities[9]->id(),
      ],
    ];

    // Entity 007.
    $return[] = [
      'text' => 'test text 1',
      'text_multi' => [
        'test text multi 1',
      ],
      'date' => $time,
      'reference' => [
        $this->entities[5]->id(),
      ],
    ];

    // Entity 008.
    $return[] = [
      'text' => 'test text 1',
      'text_multi' => [
        'test text multi 1',
      ],
      'date' => $time,
      'reference' => [
        $this->entities[8]->id(),
      ],
    ];

    // Entity 009.
    $return[] = [
      'text' => 'test text 1',
      'text_multi' => [
        'test text multi 1',
      ],
      'date' => $time,
      'reference' => [
        $this->entities[1]->id(),
      ],
    ];

    // Entity 010.
    $return[] = [
      'text' => 'test text 1',
      'text_multi' => [
        'test text multi 1',
      ],
      'date' => $time,
      'reference' => [
        $this->entities[6]->id(),
      ],
    ];

    return $return;
  }

  /**
   * Returns the SPARQL entity query.
   *
   * @param string $operator
   *   (optional) The logic operator ('AND' or 'OR'). Defaults to 'AND'.
   *
   * @return \Drupal\sparql_entity_storage\Entity\Query\Sparql\SparqlQueryInterface
   *   The SPARQL entity query.
   */
  protected function getQuery(string $operator = 'AND'): SparqlQueryInterface {
    return $this->container->get('entity_type.manager')
      ->getStorage('sparql_test')
      ->getQuery($operator)
      ->accessCheck(FALSE);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc