View source
<?php
declare (strict_types=1);
namespace Drupal\Tests\entity_share_client\Functional;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\entity_share\EntityShareUtility;
use Drupal\entity_share_test\EntityFieldHelperTrait;
use Drupal\node\NodeInterface;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\entity_share_server\Functional\EntityShareServerRequestTestTrait;
use Drupal\Tests\RandomGeneratorTrait;
use Drupal\user\UserInterface;
use Faker\Factory;
use Faker\Provider\fr_FR\PhoneNumber;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\RequestOptions;
abstract class EntityShareClientFunctionalTestBase extends BrowserTestBase {
use RandomGeneratorTrait;
use EntityShareServerRequestTestTrait;
use EntityFieldHelperTrait;
public static $modules = [
'entity_share_client_request_test',
'entity_share_client',
'entity_share_server',
'entity_share_test',
'basic_auth',
];
protected $defaultTheme = 'classy';
protected static $entityTypeId = NULL;
protected static $entityBundleId = NULL;
protected static $entityLangcode = NULL;
protected $adminUser;
protected $channelUser;
protected $entityTypeManager;
protected $remoteManager;
protected $requestService;
protected $jsonapiHelper;
protected $faker;
protected $visitedUrlsDuringSetup = [];
protected $remote;
protected $channels = [];
protected $entities = [];
protected $entitiesData;
protected function setUp() {
parent::setUp();
$this->adminUser = $this
->drupalCreateUser($this
->getAdministratorPermissions());
$this->channelUser = $this
->drupalCreateUser($this
->getChannelUserPermissions());
$this->entityTypeManager = $this->container
->get('entity_type.manager');
$this->remoteManager = $this->container
->get('entity_share_client.remote_manager');
$this->requestService = $this->container
->get('entity_share_client.request');
$this->jsonapiHelper = $this->container
->get('entity_share_client.jsonapi_helper');
$this->faker = Factory::create();
$this->faker
->addProvider(new PhoneNumber($this->faker));
$this
->createRemote($this->channelUser);
$this
->createChannel($this->channelUser);
}
protected function postSetupFixture() {
$this
->prepareContent();
$this
->populateRequestService();
$this
->deleteContent();
}
protected function getAdministratorPermissions() {
return [
'view the administration theme',
'access administration pages',
'administer_channel_entity',
];
}
protected function getChannelUserPermissions() {
return [
'entity_share_server_access_channels',
];
}
protected function getAuthenticationRequestOptions(AccountInterface $account) {
return [
RequestOptions::HEADERS => [
'Authorization' => 'Basic ' . base64_encode($account
->getAccountName() . ':' . $account->passRaw),
],
];
}
protected function createRemote(UserInterface $user) {
$remote_storage = $this->entityTypeManager
->getStorage('remote');
$remote = $remote_storage
->create([
'id' => $this
->randomMachineName(),
'label' => $this
->randomString(),
'url' => $this
->buildUrl('<front>'),
'basic_auth_username' => $user
->getAccountName(),
'basic_auth_password' => $user->passRaw,
]);
$remote
->save();
$this->remote = $remote;
}
protected function createChannel(UserInterface $user) {
$channel_storage = $this->entityTypeManager
->getStorage('channel');
$channel = $channel_storage
->create([
'id' => static::$entityTypeId . '_' . static::$entityBundleId . '_' . static::$entityLangcode,
'label' => $this
->randomString(),
'channel_entity_type' => static::$entityTypeId,
'channel_bundle' => static::$entityBundleId,
'channel_langcode' => static::$entityLangcode,
'authorized_users' => [
$user
->uuid(),
],
]);
$channel
->save();
$this->channels[$channel
->id()] = $channel;
}
protected function prepareContent() {
$entities_data = $this
->getEntitiesData();
foreach ($entities_data as $entity_type_id => $data_per_languages) {
$entity_storage = $this->entityTypeManager
->getStorage($entity_type_id);
if (!isset($this->entities[$entity_type_id])) {
$this->entities[$entity_type_id] = [];
}
foreach ($data_per_languages as $langcode => $entity_data) {
foreach ($entity_data as $entity_uuid => $entity_data_per_field) {
if (isset($this->entities[$entity_type_id][$entity_uuid])) {
$prepared_entity_data = $this
->prepareEntityData($entity_data_per_field);
$entity = $this->entities[$entity_type_id][$entity_uuid];
$entity
->addTranslation($langcode, $prepared_entity_data);
$entity
->save();
}
else {
$entity_data_per_field += [
'langcode' => [
'value' => $langcode,
'checker_callback' => 'getValue',
],
'uuid' => [
'value' => $entity_uuid,
'checker_callback' => 'getValue',
],
];
$prepared_entity_data = $this
->prepareEntityData($entity_data_per_field);
$entity = $entity_storage
->create($prepared_entity_data);
$entity
->save();
}
$this->entities[$entity_type_id][$entity_uuid] = $entity;
}
}
}
}
protected function prepareEntityData(array $entityData) {
$prepared_entity_data = [];
foreach ($entityData as $field_machine_name => $data) {
if (isset($data['value_callback'])) {
$prepared_entity_data[$field_machine_name] = call_user_func($data['value_callback']);
}
else {
$prepared_entity_data[$field_machine_name] = $data['value'];
}
}
return $prepared_entity_data;
}
protected abstract function getEntitiesDataArray();
protected function getEntitiesData() {
if (!isset($this->entitiesData)) {
$this->entitiesData = $this
->getEntitiesDataArray();
}
return $this->entitiesData;
}
protected function populateRequestService() {
$entity_share_entrypoint_url = Url::fromRoute('entity_share_server.resource_list');
$http_client = $this->remoteManager
->prepareJsonApiClient($this->remote);
$response = $this->requestService
->request($http_client, 'GET', $entity_share_entrypoint_url
->setAbsolute()
->toString());
$json_response = Json::decode((string) $response
->getBody());
foreach ($json_response['data']['channels'] as $channel_data) {
$this
->discoverJsonApiEndpoints($http_client, $channel_data['url']);
$this
->discoverJsonApiEndpoints($http_client, $channel_data['url_uuid']);
}
}
protected function discoverJsonApiEndpoints(Client $http_client, $url) {
if (in_array($url, $this->visitedUrlsDuringSetup)) {
return;
}
$this->visitedUrlsDuringSetup[] = $url;
$response = $this->requestService
->request($http_client, 'GET', $url);
$json_response = Json::decode((string) $response
->getBody());
if (is_array($json_response['data'])) {
foreach (EntityShareUtility::prepareData($json_response['data']) as $data) {
if (isset($data['relationships'])) {
foreach ($data['relationships'] as $field_data) {
if (isset($field_data['links']['related']['href'])) {
$this
->discoverJsonApiEndpoints($http_client, $field_data['links']['related']['href']);
}
}
}
if ($data['type'] == 'file--file' && isset($data['attributes']['uri']['url'])) {
try {
$this->requestService
->request($this->remoteManager
->prepareClient($this->remote), 'GET', $data['attributes']['uri']['url']);
} catch (ClientException $exception) {
}
}
}
}
if (isset($json_response['links']['next']['href'])) {
$this
->discoverJsonApiEndpoints($http_client, $json_response['links']['next']['href']);
}
}
protected function deleteContent() {
foreach ($this->entities as $entity_type_id => $entity_list) {
$entity_storage = $this->entityTypeManager
->getStorage($entity_type_id);
foreach ($entity_list as $entity_uuid => $entity) {
$entity
->delete();
$remaining_entities = $entity_storage
->loadByProperties([
'uuid' => $entity_uuid,
]);
$this
->assertTrue(empty($remaining_entities), 'The ' . $entity_type_id . ' has been deleted.');
}
}
}
protected function checkCreatedEntities() {
$entities_data = $this
->getEntitiesData();
foreach ($entities_data as $entity_type_id => $data_per_languages) {
$entity_storage = $this->entityTypeManager
->getStorage($entity_type_id);
foreach ($data_per_languages as $language_id => $entity_data) {
foreach ($entity_data as $entity_uuid => $entity_data_per_field) {
$recreated_entities = $entity_storage
->loadByProperties([
'uuid' => $entity_uuid,
]);
$this
->assertTrue(!empty($recreated_entities), 'The ' . $entity_type_id . ' with UUID ' . $entity_uuid . ' has been recreated.');
if (!empty($recreated_entities)) {
$recreated_entity = array_shift($recreated_entities);
$entity_translation = $recreated_entity
->getTranslation($language_id);
foreach ($entity_data_per_field as $field_machine_name => $data) {
if (isset($data['value_callback'])) {
$data['value'] = call_user_func($data['value_callback']);
}
if ($data['checker_callback'] == 'getFilteredStructureValues') {
$structure = array_keys($data['value'][0]);
$this
->assertEquals($data['value'], $this
->getFilteredStructureValues($entity_translation, $field_machine_name, $structure), 'The data of the field ' . $field_machine_name . ' has been recreated.');
}
else {
$this
->assertEquals($data['value'], $this
->{$data['checker_callback']}($entity_translation, $field_machine_name), 'The data of the field ' . $field_machine_name . ' has been recreated.');
}
}
}
}
}
}
}
protected function pullEveryChannels() {
$channel_infos = $this->remoteManager
->getChannelsInfos($this->remote);
$this->jsonapiHelper
->setRemote($this->remote);
$http_client = $this->remoteManager
->prepareJsonApiClient($this->remote);
foreach ($this->channels as $channel_id => $channel) {
$channel_url = $channel_infos[$channel_id]['url'];
while ($channel_url) {
$response = $this->requestService
->request($http_client, 'GET', $channel_url);
$json = Json::decode((string) $response
->getBody());
$this->jsonapiHelper
->importEntityListData(EntityShareUtility::prepareData($json['data']));
if (isset($json['links']['next']['href'])) {
$channel_url = $json['links']['next']['href'];
}
else {
$channel_url = FALSE;
}
}
}
}
protected function pullChannel($channel_id) {
$channel_infos = $this->remoteManager
->getChannelsInfos($this->remote);
$this->jsonapiHelper
->setRemote($this->remote);
$http_client = $this->remoteManager
->prepareJsonApiClient($this->remote);
$channel_url = $channel_infos[$channel_id]['url'];
while ($channel_url) {
$response = $this->requestService
->request($http_client, 'GET', $channel_url);
$json = Json::decode((string) $response
->getBody());
$this->jsonapiHelper
->importEntityListData(EntityShareUtility::prepareData($json['data']));
if (isset($json['links']['next']['href'])) {
$channel_url = $json['links']['next']['href'];
}
else {
$channel_url = FALSE;
}
}
}
protected function getEntityJsonData($channel_id, $entity_uuid) {
$json_data = [];
$channel_infos = $this->remoteManager
->getChannelsInfos($this->remote);
$this->jsonapiHelper
->setRemote($this->remote);
$http_client = $this->remoteManager
->prepareJsonApiClient($this->remote);
$channel_url = $channel_infos[$channel_id]['url'];
while ($channel_url) {
$response = $this->requestService
->request($http_client, 'GET', $channel_url);
$json = Json::decode((string) $response
->getBody());
$json_data = EntityShareUtility::prepareData($json['data']);
foreach ($json_data as $entity_json_data) {
if ($entity_json_data['id'] == $entity_uuid) {
return $entity_json_data;
}
}
if (isset($json['links']['next']['href'])) {
$channel_url = $json['links']['next']['href'];
}
else {
$channel_url = FALSE;
}
}
return $json_data;
}
protected function getCompleteMediaInfos(array $media_infos) {
return array_merge([
'status' => [
'value' => NodeInterface::PUBLISHED,
'checker_callback' => 'getValue',
],
], $media_infos);
}
protected function getCompleteNodeInfos(array $node_infos) {
return array_merge([
'type' => [
'value' => static::$entityBundleId,
'checker_callback' => 'getTargetId',
],
'title' => [
'value' => $this
->randomString(),
'checker_callback' => 'getValue',
],
], $node_infos);
}
protected function getCompleteTaxonomyTermInfos(array $taxonomy_term_infos) {
return array_merge([
'vid' => [
'value' => static::$entityBundleId,
'checker_callback' => 'getTargetId',
],
'name' => [
'value' => $this
->randomString(),
'checker_callback' => 'getValue',
],
], $taxonomy_term_infos);
}
protected function getCompleteParagraphInfos(array $paragraph_infos) {
return array_merge([
'type' => [
'value' => 'es_test',
'checker_callback' => 'getTargetId',
],
], $paragraph_infos);
}
protected function getCompleteBlockInfos(array $block_infos) {
return array_merge([
'type' => [
'value' => 'es_test',
'checker_callback' => 'getTargetId',
],
'info' => [
'value' => $this
->randomString(),
'checker_callback' => 'getValue',
],
], $block_infos);
}
protected function getEntityId($entity_type_id, $entity_uuid) {
$existing_entity_id = '';
$existing_entity = $this
->loadEntity($entity_type_id, $entity_uuid);
if (!is_null($existing_entity)) {
$existing_entity_id = $existing_entity
->id();
}
return $existing_entity_id;
}
protected function getEntityRevisionId($entity_type_id, $entity_uuid) {
$existing_entity_id = '';
$existing_entity = $this
->loadEntity($entity_type_id, $entity_uuid);
if (!is_null($existing_entity) && $existing_entity instanceof RevisionableInterface) {
$existing_entity_id = $existing_entity
->getRevisionId();
}
return $existing_entity_id;
}
protected function loadEntity($entity_type_id, $entity_uuid) {
$existing_entity = NULL;
$existing_entities = $this->entityTypeManager
->getStorage($entity_type_id)
->loadByProperties([
'uuid' => $entity_uuid,
]);
if (!empty($existing_entities)) {
$existing_entity = array_shift($existing_entities);
}
return $existing_entity;
}
protected function prepareUrlFilteredOnUuids(array $selected_entities, $channel_id) {
$channel_infos = $this->remoteManager
->getChannelsInfos($this->remote);
$channel_url = $channel_infos[$channel_id]['url'];
$parsed_url = UrlHelper::parse($channel_url);
$query = $parsed_url['query'];
$query['filter']['uuid-filter'] = [
'condition' => [
'path' => 'id',
'operator' => 'IN',
'value' => array_values($selected_entities),
],
];
$query = UrlHelper::buildQuery($query);
$prepared_url = $parsed_url['path'] . '?' . $query;
return $prepared_url;
}
protected function preparePhysicalFilesAndFileEntitiesData() {
$stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
$file_system = \Drupal::service('file_system');
$files_entities_data = [];
foreach (static::$filesData as $file_uuid => $file_data) {
$stream_wrapper = $stream_wrapper_manager
->getViaUri($file_data['uri']);
$directory_uri = $stream_wrapper
->dirname($file_data['uri']);
$file_system
->prepareDirectory($directory_uri, FileSystemInterface::CREATE_DIRECTORY);
if (isset($file_data['file_content'])) {
file_put_contents($file_data['uri'], $file_data['file_content']);
$this->filesSize[$file_uuid] = filesize($file_data['uri']);
}
elseif (isset($file_data['file_content_callback'])) {
$this
->{$file_data['file_content_callback']}($file_uuid, $file_data);
}
$files_entities_data[$file_uuid] = [
'filename' => [
'value' => $file_data['filename'],
'checker_callback' => 'getValue',
],
'uri' => [
'value' => $file_data['uri'],
'checker_callback' => 'getValue',
],
'filemime' => [
'value' => $file_data['filemime'],
'checker_callback' => 'getValue',
],
'status' => [
'value' => FILE_STATUS_PERMANENT,
'checker_callback' => 'getValue',
],
];
}
return $files_entities_data;
}
}