qbank_dam-8.x-1.4/src/QBankDAMService.php
src/QBankDAMService.php
<?php
namespace Drupal\qbank_dam;
use DOMDocument;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\file\FileRepositoryInterface;
use Drupal\file\FileUsage\DatabaseFileUsageBackend;
use Exception;
use GuzzleHttp\Client;
use QBNK\QBank\API\Credentials;
use QBNK\QBank\API\Model\MediaUsage;
use QBNK\QBank\API\QBankApi;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\Core\Render\Markup;
/**
* Class QBankDAMService.
*
* @package Drupal\qbank_dam
*/
class QBankDAMService implements QBankDAMServiceInterface
{
use StringTranslationTrait;
/**
* QBank API instance.
*
* @var \QBNK\QBank\API\QBankApi
*/
protected $QAPI;
/**
* The configuration object factory.
*
* @var \Drupal\Core\Config\ConfigFactory
*/
protected $configFactory;
/**
* Drupal\Core\Entity\EntityTypeManager definition.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Base Database API class.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* File usage manager.
*
* @var Drupal\file\FileUsage\DatabaseFileUsageBackend
*/
protected $fileUsage;
/**
* Constructor.
* The file repository.
*
* @var \Drupal\file\FileRepositoryInterface
*/
protected $fileRepository;
/**
* The file URL generator.
*
* @var \Drupal\Core\File\FileUrlGeneratorInterface
*/
protected $fileUrlGenerator;
/**
* Constructor.
*
* @param \Drupal\Core\Config\ConfigFactory $config_factory
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* @param \Drupal\Core\Database\Connection $database
* @param \Drupal\file\FileUsage\DatabaseFileUsageBackend $file_usage
* @param \Drupal\file\FileRepositoryInterface $file_repository
* @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
*/
public function __construct(ConfigFactory $config_factory, EntityTypeManagerInterface $entity_type_manager, Connection $database, DatabaseFileUsageBackend $file_usage, FileRepositoryInterface $file_repository, FileUrlGeneratorInterface $file_url_generator)
{
$this->configFactory = $config_factory;
$this->entityTypeManager = $entity_type_manager;
$this->database = $database;
$this->fileUsage = $file_usage;
$this->QAPI = NULL;
$this->fileRepository = $file_repository;
$this->fileUrlGenerator = $file_url_generator;
}
/**
* @return QBankApi|null
*/
public function getAPI()
{
try {
$conf = $this->getConfiguration();
if($this->QAPI == NULL) {
if ($conf['api_url'] &&
$conf['client_id'] &&
$conf['user'] &&
$conf['password']
) {
$this->QAPI = new QBankApi(
$conf['api_url']??'',
new Credentials(
$conf['client_id'],
$conf['user'],
$conf['password']
),
[
'log' => FALSE
]
);
} else {
$config_link = Link::fromTextAndUrl(t('QBank DAM Configuration'), Url::fromRoute('qbank_dam.qbank_dam_config_form'))->toString();
\Drupal::messenger()->addError(Markup::create('Unable to connect to QBank DAM, please check your '.$config_link));
}
}
return $this->QAPI;
} catch (\LogicException $e) {
\Drupal::logger('qbank_dam')->error($e->getMessage());
} catch (\InvalidArgumentException $e) {
\Drupal::logger('qbank_dam')->error($e->getMessage());
} catch (\Exception $e) {
\Drupal::logger('qbank_dam')->error($e->getMessage());
}
}
/**
* @param $url
* @param $client_id
* @param $user
* @param $password
* @return bool|null
*/
public function checkConfiguration($url, $client_id, $user, $password)
{
try {
$test = new QBankApi(
$url??'',
new Credentials($client_id, $user, $password),
['log' => FALSE,]
);
$test->getTokens();
} catch (Exception $e) {
\Drupal::logger('qbank_dam')->error($e->getMessage());
return NULL;
}
return TRUE;
}
/**
* @return bool|null
*/
public function checkStoredConfiguration()
{
return $this->checkConfiguration(
$this->getApiUrl(),
$this->getClientId(),
$this->getUser(),
$this->getpassword()
);
}
/**
* @return array
*/
public function getConfiguration()
{
return [
'protocol' => $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('protocol'),
'api_url' => $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('api_url'),
'client_id' => $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('client_id'),
'user' => $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('user'),
'password' => $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('password'),
];
}
/**
* @return array|mixed|null
*/
public function getProtocol()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('protocol');
}
/**
* @return array|mixed|null
*/
public function getApiUrl()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('api_url');
}
/**
* @return array|mixed|null
*/
public function getClientId()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('client_id');
}
/**
* @return array|mixed|null
*/
public function getUser()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')->get('user');
}
/**
* @return array|mixed|null
*/
public function getpassword()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('password');
}
/**
* @return array|mixed|null
*/
public function getDeploymentSite()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('deployment_site');
}
/**
* @return array|mixed|null
*/
public function getSessionId()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('session_id');
}
/**
* @return array|mixed|null
*/
public function getFieldMap()
{
return $this->configFactory->get('qbank_dam.qbankdamconfig')
->get('map');
}
/**
* @return mixed
*/
public function getToken()
{
$this->getAPI();
if ($this->QAPI) {
return $this->QAPI->getTokens()['accessToken'];
}
}
/**
* @return array
*/
public function getDeploymentSites()
{
$this->getAPI();
$sites = [];
$list = [];
if ($this->QAPI) {
try {
$deployment = $this->QAPI->deployment();
$list = $deployment->listSites();
} catch (Exception $e) {
$list = [];
}
}
foreach ($list as $site) {
$sites[$site->getId()] = $site->getName();
}
if (count($sites) > 0) {
return $sites;
} else {
return [
'No site' => $this->t('No site'),
];
}
}
/**
* @param $url
* @param $media_id
* @return \Drupal\file\FileInterface|false|null
*/
public function download($url, $media_id)
{
$file = NULL;
$client = new Client();
$response = $client->get($url);
if ($response->getStatusCode() == 200) {
$filenameOriginalURLencoded = str_replace('"', '', explode('filename=', $response->getHeader('content-disposition')[0])[1]);
$filenameOriginal = urldecode($filenameOriginalURLencoded);
$filenameParts = explode('.', $filenameOriginal);
$ext = array_pop($filenameParts);
$filenameOnly = implode('.', $filenameParts);
$filename = $filenameOnly . date('YmdHis') . '.' . $ext;
if ($filename) {
$file_data = $response->getBody()->getContents();
$directory = 'public://qbank/';
\Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
$file = $this->fileRepository->writeData($file_data, $directory . $filename, FileSystemInterface::CREATE_DIRECTORY);
}
if ($file) {
$this->database->update('file_managed')
->fields([
'qbank_origin_type' => 'qbank',
'qbank_origin_id' => $media_id,
])
->condition('fid', $file->Id(), '=')
->execute();
}
}
return $file;
}
/**
* @param $entity
*/
public function deleteUsage($entity)
{
$this->database->delete('file_usage')
->condition('module', 'media')
->condition('id', $entity->Id())
->execute();
}
/**
* @param $entity
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function addUsage($entity, $entity_machine_name,$field_name_arr)
{
$this->qbankFilterAddFileUsageFromFields($entity);
$this->qbankAddUsage($entity, $entity_machine_name, $field_name_arr);
}
/**
* Add file usage from file references in an entity's text fields.
*/
private function qbankFilterAddFileUsageFromFields($entity)
{
// Track the total usage for files from all fields combined.
$entity_files = $this->qbankEntityFieldCountFiles($entity);
$entity_id = $entity->Id();
// When an entity has revisions and then is saved again NOT as new version the
// previous revision of the entity has be loaded to get the last known good
// count of files. The saved data is compared against the last version
// so that a correct file count can be created for that (the current) version
// id. This code may assume some things about entities that are only true for
// node objects. This should be reviewed.
if (!($entity->isNew())) {
$old_files = $this->qbankEntityFieldCountFiles($this->entityTypeManager->getStorage($entity->getEntityTypeId())
->load($entity->id()));
foreach ($old_files as $fid => $old_file_count) {
// Were there more files on the node just prior to saving?
if (empty($entity_files[$fid])) {
$entity_files[$fid] = 0;
}
if ($old_file_count > $entity_files[$fid]) {
$deprecate = $old_file_count - $entity_files[$fid];
// Now deprecate this usage
$file = $this->entityTypeManager->getStorage('file')->load($fid);
if ($file) {
$this->fileUsage->delete($file, 'media', $entity->getEntityType()
->id(), $entity_id, $deprecate);
}
// Usage is deleted, nothing more to do with this file
unset($entity_files[$fid]);
} // There are the same number of files, nothing to do
elseif ($entity_files[$fid] == $old_file_count) {
unset($entity_files[$fid]);
}
// There are more files now, adjust the difference for the greater number.
// file_usage incrementing will happen below.
else {
// We just need to adjust what the file count will account for the new
// images that have been added since the increment process below will
// just add these additional ones in
$entity_files[$fid] = $entity_files[$fid] - $old_file_count;
}
}
}
// Each entity revision counts for file usage. If versions are not enabled
// the file_usage table will have no entries for this because of the delete
// query above.
foreach ($entity_files as $fid => $entity_count) {
if ($file = $this->entityTypeManager->getStorage('file')->load($fid)) {
$this->fileUsage->add($file, 'media', $file->getEntityTypeId(), $fid, $entity_count);
}
}
}
/**
* Parse file references from an entity's text fields and return them as an
* array.
*/
private function qbankFilterParseFromFields($entity)
{
$file_references = [];
foreach ($this->qbankFilterFieldsWithTextFiltering($entity) as $field_name) {
$field = $entity->get($field_name);
if (!empty($field->getValue())) {
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($field->getValue(TRUE)[0]['value']);
$imgs = $doc->getElementsByTagName('img');
foreach ($imgs as $img) {
$filename = explode('/', $img->getAttribute('src'));
$filename = $filename[sizeof($filename) - 1];
$query = $this->entityTypeManager->getStorage('file')->getQuery();
$query->accessCheck(FALSE);
$result = $query->condition('uri', '%/' . $filename, 'LIKE')
->execute();
$fid = reset($result);
$file_references[] = [
'fid' => $fid,
'filename' => $filename,
];
}
}
}
return $file_references;
}
/**
* Utility function to get the file count in this entity
*
* @param type $entity
*
* @return int
*/
private function qbankEntityFieldCountFiles($entity)
{
$entity_files = [];
foreach ($this->qbankFilterParseFromFields($entity) as $file_reference) {
if (empty($entity_files[$file_reference['fid']])) {
$entity_files[$file_reference['fid']] = 1;
} else {
$entity_files[$file_reference['fid']]++;
}
}
return $entity_files;
}
/**
* Returns an array containing the names of all fields that perform text
* filtering.
*/
private function qbankFilterFieldsWithTextFiltering($entity)
{
// Get all of the fields on this entity that allow text filtering.
$fields_with_text_filtering = [];
foreach ($entity->getFieldDefinitions() as $field_name => $field) {
if (array_key_exists('format', $field->getFieldStorageDefinition()
->getPropertyDefinitions())) {
$fields_with_text_filtering[] = $field_name;
}
}
return $fields_with_text_filtering;
}
/**
* @param $node
* @param $node_machine_name
* @param $field_name_arr
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
private function qbankAddUsage($node, $node_machine_name,$field_name_arr)
{
\Drupal::logger('qbank_dam')->notice('In QBDAMService::qbankAddUsage with Node : ' . $node->Id());
// To select images added from Tinymce
$query1 = $this->database->select('file_usage', 'fu');
$query1->join('file_managed', 'fm', 'fu.fid = fm.fid');
$query1->fields('fm', ['fid', 'uri', 'qbank_origin_id', 'uid']);
$query1->fields('fu', ['id']);
$query1->condition('fu.id', $node->Id(), '=');
$query1->condition('fm.qbank_origin_type', 'qbank', '=');
$query1->condition('fu.type', 'node', '=');
// To select images added from Media Block
for ($i=0; $i < count($field_name_arr); $i++) {
$tbl_name = 'node__'.$field_name_arr[$i];
$tbl_field_name = 'fqm.'.$field_name_arr[$i].'_target_id' ;
$query = $this->database->select($tbl_name, 'fqm');
$query->join('file_usage', 'fu', $tbl_field_name.'= fu.id');
$query->join('file_managed', 'fm', 'fu.fid = fm.fid');
$query->fields('fm', ['fid', 'uri', 'qbank_origin_id', 'uid']);
$query->fields('fu', ['id']);
$query->condition('entity_id', $node->Id(), '=');
$query->condition('fm.qbank_origin_type', 'qbank', '=');
$query->condition('fu.type', 'media', '=');
$query1 = $query->union($query1,'UNION');
}
try {
$r = $query1->execute();
} catch (\Exception $e) {
\Drupal::logger('qbank_dam')->error($e->getMessage());
}
$qbankapi = $this->getAPI();
$sessionHash = \Drupal::service('session')->getId();
try {
$qbank_session = $qbankapi->events()->session(
// $this->getDeploymentSite(),
$this->getSessionId(),
$sessionHash,
gethostbyname($_SERVER['HTTP_HOST']),
'drupal'
);
} catch (\Exception $e) {
\Drupal::logger('qbank_dam')->error($e->getMessage());
}
while ($record = $r->fetchAssoc()) {
$user = $this->entityTypeManager->getStorage('user')
->load($record['uid']);
$mediaUsage = new MediaUsage([
'mediaId' => $record['qbank_origin_id'],
'mediaUrl' => $this->fileUrlGenerator->generateAbsoluteString($record['uri']),
'pageUrl' => \Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => $node->Id()], ['absolute' => TRUE])
->toString(),
'language' => 'eng', //Three character language ISO
'context' => [
'localID' => $record['fid'],
'cropCoords' => [],
'pageTitle' => $node->getTitle(),
'createdByName' => $user->name->value,
'createdByEmail' => $user->mail->value,
],
]);
$mediaUsageResponse = $qbankapi->events()->addUsage(
$qbank_session,
$mediaUsage
);
\Drupal::logger('qbank_dam')->notice('Qbank Usage saved for mediaId : ' . $record['qbank_origin_id']);
};
}
/**
* This method provides the image information from image ID, we read image properties from the returing object of the API.
*
* @param integer $qbank_id
*
* @return QBNK\QBank\API\Model\MediaResponse $property
*/
public function getMediaProperties($qbank_id)
{
$property = $this->getAPI()->media()->retrieveMedia($qbank_id);
return $property;
}
/**
* This method provides the image information from image ID, we read image properties from the returing object of the API.
*
* @param integer $qbank_id
*
* @return QBNK\QBank\API\Model\MediaResponse $property
*/
public function getMedia($media_id)
{
$media = $this->getAPI()->media()->retrieveMedia($media_id);
return $media;
}
/**
* This method provides the suitable templates based on the classification of the media
*
* @param integer $qbank_id
*
* @return QBNK\QBank\API\Model\MediaResponse $property
*/
public function findSuitableTemplateId($classification, $deployed_files = [], $selection = ''){
$templates = [];
if(!empty($deployed_files)){
foreach($deployed_files as $deployed_file){
if($deployed_file->getDeploymentSiteId() == $this->getDeploymentSite()){
switch($classification){
case 'image':
if($deployed_file->getImageTemplateId()){
$templates[] = $deployed_file->getImageTemplateId();
}
break;
case 'video':
if($deployed_file->getVideoTemplateId()){
$templates[] = $deployed_file->getVideoTemplateId();
}
break;
case 'document':
if($deployed_file->getDocumentTemplateId()){
$templates[] = $deployed_file->getDocumentTemplateId();
}
break;
default:
}
if($deployed_file->getTemplateName() == null){
$templates[] = '';
}
}
}
}
return $templates;
}
}
