Files
Phraseanet/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php
Aina Sitraka 80d5c400bd PHRAS-4069: Prod - expose-cli - search publication and parent publication (#4515)
* expose cli fix parent publication

* translate and yarn.lock file

* some css fix

* expose search publication title filter

* display nb items

* trigger only from more than 3 character

* do not display publication in to his parent list

* trigger search publication on empty search
2024-06-06 18:24:18 +02:00

434 lines
14 KiB
PHP

<?php
namespace Alchemy\Phrasea\Twig;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Collection\CollectionHelper;
use Alchemy\Phrasea\Http\StaticFile\StaticMode;
use Alchemy\Phrasea\Model\Entities\ElasticsearchRecord;
use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\RecordInterface;
use Alchemy\Phrasea\Model\Repositories\UserRepository;
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Flag;
class PhraseanetExtension extends \Twig_Extension
{
/** @var Application */
private $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function getFilters()
{
return array(
new \Twig_SimpleFilter('sort_collections', array(CollectionHelper::class, 'sort')),
new \Twig_SimpleFilter('date_duration', array($this, 'getDuration')),
new \Twig_SimpleFilter('json_to_array', array($this, 'jsonToArray')),
);
}
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('user_setting', array($this, 'getUserSetting')),
new \Twig_SimpleFunction('record_thumbnail_url', array($this, 'getThumbnailUrl')),
new \Twig_SimpleFunction('record_subdef_url', array($this, 'getSubdefUrl')),
new \Twig_SimpleFunction('record_subdef_size', array($this, 'getSubdefSize')),
new \Twig_SimpleFunction('record_doctype_icon', array($this, 'getDoctypeIcon'), array(
'is_safe' => array('html')
)),
new \Twig_SimpleFunction('has_access_subdef', array($this, 'hasAccessSubDefinition')),
new \Twig_SimpleFunction('record_thumbnailgif_url', array($this, 'getThumbnailGifUrl')),
new \Twig_SimpleFunction('granted_on_collection', array($this, 'isGrantedOnCollection')),
new \Twig_SimpleFunction('granted_on_databox', array($this, 'isGrantedOnDatabox')),
new \Twig_SimpleFunction('collection_logo', array($this, 'getCollectionLogo'), array(
'is_safe' => array('html')
)),
new \Twig_SimpleFunction('record_flags', array($this, 'getRecordFlags')),
new \Twig_SimpleFunction('border_checker_from_fqcn', array($this, 'getCheckerFromFQCN')),
new \Twig_SimpleFunction('caption_field', array($this, 'getCaptionField')),
new \Twig_SimpleFunction('caption_field_label', array($this, 'getCaptionFieldLabel')),
new \Twig_SimpleFunction('caption_field_gui_visible', array($this, 'getCaptionFieldGuiVisible')),
new \Twig_SimpleFunction('caption_field_order', array($this, 'getCaptionFieldOrder')),
new \Twig_SimpleFunction('flag_slugify', array(Flag::class, 'normalizeName')),
new \Twig_SimpleFunction('user_display_name', array($this, 'getUserDisplayName')),
);
}
public function getGlobals()
{
return [
// change this version when you change JS file to force the navigation to reload js file
'assetFileVersion' => 106
];
}
public function getDuration(int $interval)
{
$t = round($interval);
return sprintf('%02d h %02d m %02d s', ($t/3600),($t/60 %60), $t%60);
}
/**
* get localized field's label
* @param RecordInterface $record
* @param $fieldName
* @return string - the name label
*/
public function getCaptionFieldLabel(RecordInterface $record, $fieldName)
{
if ($record) {
/** @var \appbox $appbox */
$appbox = $this->app['phraseanet.appbox'];
$databox = $appbox->get_databox($record->getDataboxId());
foreach ($databox->get_meta_structure() as $meta) {
/** @var \databox_field $meta */
if ($meta->get_name() === $fieldName) {
return $meta->get_label($this->app['locale']);
}
}
}
return '';
}
/**
* get localized field's gui_visible
* @param RecordInterface $record
* @param $fieldName
* @return string - the name gui_visible
*/
public function getCaptionFieldGuiVisible(RecordInterface $record, $fieldName)
{
if ($record) {
/** @var \appbox $appbox */
$appbox = $this->app['phraseanet.appbox'];
$databox = $appbox->get_databox($record->getDataboxId());
foreach ($databox->get_meta_structure() as $meta) {
/** @var \databox_field $meta */
if ($meta->get_name() === $fieldName) {
return $meta->get_gui_visible($this->app['locale']);
}
}
}
return '';
}
public function getCaptionField(RecordInterface $record, $field, $value)
{
if ($record instanceof ElasticsearchRecord) {
$highlights = $record->getHighlight();
if (false === isset($highlights[$field])) {
return implode('; ', (array) $value);
}
$highlightValue = $highlights[$field];
// if field is multivalued, merge highlighted values with captions ones
if (is_array($value) && count($value) > 1) {
$highlightValue = array_merge($highlightValue, array_diff($value, array_map(function($value) {
return str_replace(array('[[em]]', '[[/em]]'), array('', ''), $value);
}, $highlightValue)));
}
return implode('; ', (array) $highlightValue);
}
return implode('; ', (array) $value);
}
/**
* @param RecordInterface $record
* @param bool $businessFields
* @return array
*/
public function getCaptionFieldOrder(RecordInterface $record, $businessFields)
{
static $orders = [];
$databoxId = $record->getDataboxId();
$orderKey = (bool) $businessFields ? 'business' : 'public';
if (!isset($orders[$databoxId][$orderKey])) {
/** @var \appbox $appbox */
$appbox = $this->app['phraseanet.appbox'];
$databox = $appbox->get_databox($databoxId);
$orders[$databoxId] = $this->retrieveDataboxFieldOrderings($databox);
}
return $orders[$databoxId][$orderKey];
}
/**
* @param \databox $databox
* @return array
*/
private function retrieveDataboxFieldOrderings(\databox $databox)
{
$publicOrder = [];
$businessOrder = [];
foreach ($databox->get_meta_structure() as $field) {
$fieldName = $field->get_name();
if (!$field->isBusiness()) {
$publicOrder[] = $fieldName;
}
$businessOrder[] = $fieldName;
};
return [
'public' => $publicOrder,
'business' => $businessOrder,
];
}
public function getRecordFlags(RecordInterface $record)
{
$recordStatuses = [];
/** @var \appbox $appbox */
$appbox = $this->app['phraseanet.appbox'];
$databox = $appbox->get_databox($record->getDataboxId());
$structure = $databox->getStatusStructure()->toArray();
if (!$this->isGrantedOnCollection($record->getBaseId(), [\ACL::CHGSTATUS])) {
$structure = array_filter($structure, function($status) {
return (bool) $status['printable'];
});
}
$bitValue = $record->getStatusBitField();
foreach ($structure as $status) {
$on = \databox_status::bitIsSet($bitValue, $status['bit']);
if (null === ($on ? $status['img_on'] : $status['img_off'])) {
continue;
}
$recordStatuses[] = [
'path' => ($on ? $status['img_on'] : $status['img_off']),
'labels' => ($on ? $status['labels_on_i18n'] : $status['labels_off_i18n'])
];
}
return $recordStatuses;
}
/**
* returns true if user is authenticated and has all the passed rights on the base
* todo : wtf $rights is an array since it's never called with more than 1 right in it ?
*
* @param $baseId
* @param array $rights
* @return bool
* @throws \Exception
*/
public function isGrantedOnCollection($baseId, Array $rights)
{
if (false === ($this->app->getAuthenticatedUser() instanceof User)) {
return false;
}
$acl = $this->app->getAclForUser($this->app->getAuthenticatedUser());
foreach ($rights as $right) {
if (! $acl->has_right_on_base($baseId, $right)) {
return false;
}
}
return true;
}
public function isGrantedOnDatabox($databoxId, $rights)
{
if (false === ($this->app->getAuthenticatedUser() instanceof User)) {
return false;
}
$rights = (array)$rights;
foreach ($rights as $right) {
if (false === $this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_sbas($databoxId, $right)) {
return false;
}
}
return true;
}
public function getCollectionLogo($baseId)
{
if (false === $this->app['filesystem']->exists(sprintf('%s/config/minilogos/%s', $this->app['root.path'], $baseId))) {
return '';
}
return sprintf(
'<img title="%s" src="/custom/minilogos/%s" />',
\phrasea::bas_labels($baseId, $this->app),
$baseId
);
}
public function hasAccessSubDefinition(RecordInterface $record, $subDefinition)
{
if (false === ($this->app->getAuthenticatedUser() instanceof User)) {
return false;
}
return $this->app->getAclForUser($this->app->getAuthenticatedUser())->has_access_to_subdef($record, $subDefinition);
}
public function getDoctypeIcon(RecordInterface $record)
{
$src = $title = '';
if ($record->isStory()) {
$src = '/assets/common/images/icons/icon_story.gif';
$title = $this->app['translator']->trans('reportage');
return sprintf('<img src="%s" title="%s" />', $src, $title);
}
switch ($record->getType()) {
case 'image':
$src = '/assets/common/images/icons/icon_image.png';
$title = $this->app['translator']->trans('image');
break;
case 'document':
$src = '/assets/common/images/icons/icon_document.png';
$title = $this->app['translator']->trans('document');
break;
case 'video':
$src = '/assets/common/images/icons/icon_video.png';
$title = $this->app['translator']->trans('video');
break;
case 'audio':
$src = '/assets/common/images/icons/icon_audio.png';
$title = $this->app['translator']->trans('audio');
break;
case 'flash':
$src = '/assets/common/images/icons/icon_flash.png';
$title = $this->app['translator']->trans('flash');
break;
}
return sprintf('<img src="%s" title="%s" />', $src, $title);
}
public function getThumbnailUrl(RecordInterface $record)
{
return $this->getSubdefUrl($record, 'thumbnail');
}
public function getSubdefUrl(RecordInterface $record, $subdefName)
{
/** @var StaticMode $staticMode */
$staticMode = $this->app['phraseanet.static-file'];
if ($record instanceof ElasticsearchRecord) {
$subdefs = $record->getSubdefs();
if (isset($subdefs[$subdefName])) {
$thumbnail = $subdefs[$subdefName];
if (null !== $path = $thumbnail['path']) {
if (is_string($path) && '' !== $path) {
$etag = dechex(crc32(dechex($record->getVersion() ^ 0x5A5A5A5A)));
return $staticMode->getUrl($path, $etag);
}
}
}
} elseif ($record instanceof \record_adapter) {
if (null !== $thumbnail = $record->get_subdef($subdefName)) {
if ('' !== $path = $thumbnail->getRealPath()) {
$etag = $thumbnail->getEtag();
return $staticMode->getUrl($path, $etag);
}
}
}
$path = sprintf('/assets/common/images/icons/substitution/%s.png',
str_replace('/', '_', $record->getMimeType())
);
return $path;
}
public function getThumbnailGifUrl(RecordInterface $record)
{
return $this->getSubdefUrl($record, 'thumbnailgif');
}
public function getSubdefSize(RecordInterface $record, $subdefName)
{
$ret = null;
if ($record instanceof ElasticsearchRecord) {
$subdefs = $record->getSubdefs();
if (isset($subdefs[$subdefName])) {
$subdef = $subdefs[$subdefName];
if (isset($subdef['width']) && $subdef['width'] !== null && isset($subdef['height']) && $subdef['height'] !== null) {
$ret = [
'width' => $subdef['width'],
'height' => $subdef['height']
];
}
}
} elseif ($record instanceof \record_adapter) {
if (null !== $subdef = $record->get_subdef($subdefName)) {
$ret = [
'width' => $subdef->get_width(),
'height' => $subdef->get_height()
];
}
}
return $ret;
}
public function jsonToArray($string)
{
return json_decode($string, true);
}
public function getUserSetting($setting, $default = null)
{
if (false === ($this->app->getAuthenticatedUser() instanceof User)) {
return $default;
}
return $this->app['settings']->getUserSetting($this->app->getAuthenticatedUser(), $setting, $default);
}
public function getCheckerFromFQCN($checkerFQCN)
{
return $this->app['border-manager']->getCheckerFromFQCN($checkerFQCN);
}
public function getUserDisplayName($userId)
{
/** @var User $user */
$user = $this->app['repo.users']->find($userId);
return ($user == null) ? '' : $user->getDisplayName();
}
public function getName()
{
return 'phraseanet';
}
}