Merge branch 'master' of https://github.com/alchemy-fr/Phraseanet into PHRAS-859_validation_special_characters_status

This commit is contained in:
Mike Ng
2018-05-24 15:25:51 +04:00
18 changed files with 3302 additions and 3027 deletions

View File

@@ -127,6 +127,23 @@ class TwigServiceProvider implements ServiceProviderInterface
);
}, ['needs_environment' => true, 'is_safe' => ['html']]));
$twig->addFilter(new \Twig_SimpleFilter('parseColor', function (\Twig_Environment $twig, $string) use ($app) {
$re = '/^(.*)\[#([0-9a-fA-F]{6})]$/m';
$stringArr = explode(';', $string);
foreach ($stringArr as $key => $value) {
preg_match_all($re, trim($value), $matches);
if ($matches && $matches[1] != null && $matches[2] != null) {
$colorCode = '#' . $matches[2][0];
$colorName = $matches[1][0];
$stringArr[$key] = '<span style="white-space: nowrap;"><span class="color-dot" style="margin-right: 4px; background-color: ' . $colorCode . '"></span>' . $colorName . '</span>';
}
}
return implode('; ', $stringArr);
}, ['needs_environment' => true, 'is_safe' => ['html']]));
$twig->addFilter(new \Twig_SimpleFilter('bounce',
function (\Twig_Environment $twig, $fieldValue, $fieldName, $searchRequest, $sbasId) {
// bounce value if it is present in thesaurus as well

View File

@@ -25,6 +25,7 @@ class PDF
const LAYOUT_PREVIEWCAPTIONTDM = 'previewCaptionTdm';
const LAYOUT_THUMBNAILLIST = 'thumbnailList';
const LAYOUT_THUMBNAILGRID = 'thumbnailGrid';
const LAYOUT_CAPTION = 'caption';
public function __construct(Application $app, array $records, $layout)
{
@@ -73,6 +74,8 @@ class PDF
continue 2;
}
break;
case self::LAYOUT_CAPTION:
break;
}
$record->setNumber(count($list) + 1);
@@ -106,6 +109,9 @@ class PDF
case self::LAYOUT_THUMBNAILGRID:
$this->print_thumbnailGrid();
break;
case self::LAYOUT_CAPTION:
$this->print_caption();
break;
}
return $this;
@@ -315,6 +321,67 @@ class PDF
$this->pdf->SetLeftMargin($lmargin);
}
protected function print_caption()
{
$this->pdf->AddPage();
$oldMargins = $this->pdf->getMargins();
$lmargin = $oldMargins['left'];
$rmargin = $oldMargins['right'];
foreach ($this->records as $rec) {
$title = "record : " . $rec->get_title();
$y = $this->pdf->GetY();
if($this->pdf->getPageHeight() - $y < 20){ // height of the footer is 15
$this->pdf->AddPage();
$y = $oldMargins['top'];
}
$t = \phrasea::bas_labels($rec->getBaseId(), $this->app);
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
$this->pdf->SetFillColor(220, 220, 220);
$this->pdf->SetLeftMargin($lmargin);
$this->pdf->SetRightMargin($rmargin);
$this->pdf->SetX($lmargin);
$this->pdf->SetY($y);
$this->pdf->out = false;
$this->pdf->MultiCell(140, 4, $title, "LTR", "L", 1);
$y2 = $this->pdf->GetY();
$h = $y2 - $y;
$this->pdf->out = true;
$this->pdf->SetX($lmargin);
$this->pdf->SetY($y);
$this->pdf->Cell(0, $h, "", "LTR", 1, "R", 1);
$this->pdf->SetX($lmargin);
$this->pdf->SetY($y);
$this->pdf->Cell(0, 4, $t, "", 1, "R");
$this->pdf->SetX($lmargin);
$this->pdf->SetY($y);
$this->pdf->MultiCell(140, 4, $title, "", "L");
$this->pdf->SetX($lmargin);
$this->pdf->SetY($y = $y2);
$this->pdf->SetY($y + 2);
foreach ($rec->get_caption()->get_fields() as $field) {
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
$this->pdf->Write(5, $field->get_name() . " : ");
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
$t = str_replace(
["&lt;", "&gt;", "&amp;"]
, ["<", ">", "&"]
, strip_tags($field->get_serialized_values())
);
$this->pdf->Write(5, $t);
$this->pdf->Write(6, "\n");
}
$this->pdf->SetY($this->pdf->GetY() + 10);
}
}
protected function print_preview($withtdm, $write_caption)
{
if ($withtdm === true) {

View File

@@ -201,6 +201,11 @@ class ElasticSearchEngine implements SearchEngineInterface
$this->notImplemented();
}
private function notImplemented()
{
throw new LogicException('Not implemented');
}
/**
* {@inheritdoc}
*/
@@ -241,11 +246,6 @@ class ElasticSearchEngine implements SearchEngineInterface
$this->notImplemented();
}
private function notImplemented()
{
throw new LogicException('Not implemented');
}
/**
* {@inheritdoc}
*/
@@ -330,131 +330,6 @@ class ElasticSearchEngine implements SearchEngineInterface
);
}
private function buildHighlightRules(QueryContext $context)
{
$highlighted_fields = [];
foreach ($context->getHighlightedFields() as $field) {
switch ($field->getType()) {
case FieldMapping::TYPE_STRING:
$index_field = $field->getIndexField();
$raw_index_field = $field->getIndexField(true);
$highlighted_fields[$index_field] = [
// Requires calling Mapping::enableTermVectors() on this field mapping
'matched_fields' => [$index_field, $raw_index_field],
'type' => 'fvh'
];
break;
case FieldMapping::TYPE_FLOAT:
case FieldMapping::TYPE_DOUBLE:
case FieldMapping::TYPE_INTEGER:
case FieldMapping::TYPE_LONG:
case FieldMapping::TYPE_SHORT:
case FieldMapping::TYPE_BYTE:
continue;
case FieldMapping::TYPE_DATE:
default:
continue;
}
}
return [
'pre_tags' => ['[[em]]'],
'post_tags' => ['[[/em]]'],
'order' => 'score',
'fields' => $highlighted_fields
];
}
/**
* {@inheritdoc}
*/
public function autocomplete($query, SearchEngineOptions $options)
{
$params = $this->createCompletionParams($query, $options);
$res = $this->client->suggest($params);
$ret = [
'text' => [],
'byField' => []
];
foreach(array_keys($params['body']) as $fname) {
$t = [];
foreach($res[$fname] as $suggest) { // don't know why there is a sub-array level
foreach($suggest['options'] as $option) {
$text = $option['text'];
if(!in_array($text, $ret['text'])) {
$ret['text'][] = $text;
}
$t[] = [
'label' => $text,
'query' => $fname.':'.$text
];
}
}
if(!empty($t)) {
$ret['byField'][$fname] = $t;
}
}
return $ret;
}
/**
* {@inheritdoc}
*/
public function resetCache()
{
}
/**
* {@inheritdoc}
*/
public function clearCache()
{
}
/**
* {@inheritdoc}
*/
public function clearAllCache(\DateTime $date = null)
{
}
private function createCompletionParams($query, SearchEngineOptions $options)
{
$body = [];
$context = [
'record_type' => $options->getSearchType() === SearchEngineOptions::RECORD_RECORD ?
SearchEngineInterface::GEM_TYPE_RECORD : SearchEngineInterface::GEM_TYPE_STORY
];
$base_ids = $options->getBasesIds();
if (count($base_ids) > 0) {
$context['base_id'] = $base_ids;
}
$search_context = $this->context_factory->createContext($options);
$fields = $search_context->getUnrestrictedFields();
foreach($fields as $field) {
if($field->getType() == FieldMapping::TYPE_STRING) {
$k = '' . $field->getName();
$body[$k] = [
'text' => $query,
'completion' => [
'field' => "caption." . $field->getName() . ".suggest",
'context' => &$context
]
];
}
}
return [
'index' => $this->indexName,
'body' => $body
];
}
private function createRecordQueryParams($ESQuery, SearchEngineOptions $options, \record_adapter $record = null)
{
$params = [
@@ -483,66 +358,28 @@ class ElasticSearchEngine implements SearchEngineInterface
return $params;
}
private function getAggregationQueryParams(SearchEngineOptions $options)
private function createSortQueryParams(SearchEngineOptions $options)
{
$aggs = [];
// technical aggregates (enable + optional limit)
foreach (ElasticsearchOptions::getAggregableTechnicalFields() as $k => $f) {
$size = $this->options->getAggregableFieldLimit($k);
if ($size !== databox_field::FACET_DISABLED) {
if ($size === databox_field::FACET_NO_LIMIT) {
$size = ESField::FACET_NO_LIMIT;
}
$agg = [
'terms' => [
'field' => $f['field'],
'size' => $size
]
];
$aggs[$k] = $agg;
}
}
// fields aggregates
$structure = $this->context_factory->getLimitedStructure($options);
foreach ($structure->getFacetFields() as $name => $field) {
// 2015-05-26 (mdarse) Removed databox filtering.
// It was already done by the ACL filter in the query scope, so no
// document that shouldn't be displayed can go this far.
$agg = [
'terms' => [
'field' => $field->getIndexField(true),
'size' => $field->getFacetValuesLimit()
]
];
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
}
return $aggs;
}
$sort = [];
private function createACLFilters(SearchEngineOptions $options)
{
// No ACLs if no user
if (false === $this->app->getAuthenticator()->isAuthenticated()) {
return [];
if ($options->getSortBy() === null || $options->getSortBy() === SearchEngineOptions::SORT_RELEVANCE) {
$sort['_score'] = $options->getSortOrder();
}
elseif ($options->getSortBy() === SearchEngineOptions::SORT_CREATED_ON) {
$sort['created_on'] = $options->getSortOrder();
}
elseif ($options->getSortBy() === 'recordid') {
$sort['record_id'] = $options->getSortOrder();
}
else {
$sort[sprintf('caption.%s', $options->getSortBy())] = $options->getSortOrder();
}
$acl = $this->app->getAclForUser($this->app->getAuthenticatedUser());
$grantedCollections = array_keys($acl->get_granted_base([\ACL::ACTIF]));
if (count($grantedCollections) === 0) {
return ['bool' => ['must_not' => ['match_all' => new \stdClass()]]];
if (!array_key_exists('record_id', $sort)) {
$sort['record_id'] = $options->getSortOrder();
}
$appbox = $this->app['phraseanet.appbox'];
$flagNamesMap = $this->getFlagsKey($appbox);
// Get flags rules
$flagRules = $this->getFlagsRules($appbox, $acl, $grantedCollections);
// Get intersection between collection ACLs and collection chosen by end user
$aclRules = $this->getACLsByCollection($flagRules, $flagNamesMap);
return $this->buildACLsFilters($aclRules, $options);
return $sort;
}
private function createQueryFilters(SearchEngineOptions $options)
@@ -600,27 +437,6 @@ class ElasticSearchEngine implements SearchEngineInterface
return $filters;
}
private function createSortQueryParams(SearchEngineOptions $options)
{
$sort = [];
if ($options->getSortBy() === null || $options->getSortBy() === SearchEngineOptions::SORT_RELEVANCE) {
$sort['_score'] = $options->getSortOrder();
} elseif ($options->getSortBy() === SearchEngineOptions::SORT_CREATED_ON) {
$sort['created_on'] = $options->getSortOrder();
} elseif ($options->getSortBy() === 'recordid') {
$sort['record_id'] = $options->getSortOrder();
} else {
$sort[sprintf('caption.%s', $options->getSortBy())] = $options->getSortOrder();
}
if (! array_key_exists('record_id', $sort)) {
$sort['record_id'] = $options->getSortOrder();
}
return $sort;
}
private function getFlagsKey(\appbox $appbox)
{
$flags = [];
@@ -635,6 +451,32 @@ class ElasticSearchEngine implements SearchEngineInterface
return $flags;
}
private function createACLFilters(SearchEngineOptions $options)
{
// No ACLs if no user
if (false === $this->app->getAuthenticator()->isAuthenticated()) {
return [];
}
$acl = $this->app->getAclForUser($this->app->getAuthenticatedUser());
$grantedCollections = array_keys($acl->get_granted_base([\ACL::ACTIF]));
if (count($grantedCollections) === 0) {
return ['bool' => ['must_not' => ['match_all' => new \stdClass()]]];
}
$appbox = $this->app['phraseanet.appbox'];
$flagNamesMap = $this->getFlagsKey($appbox);
// Get flags rules
$flagRules = $this->getFlagsRules($appbox, $acl, $grantedCollections);
// Get intersection between collection ACLs and collection chosen by end user
$aclRules = $this->getACLsByCollection($flagRules, $flagNamesMap);
return $this->buildACLsFilters($aclRules, $options);
}
private function getFlagsRules(\appbox $appbox, \ACL $acl, array $collections)
{
$rules = [];
@@ -766,4 +608,166 @@ class ElasticSearchEngine implements SearchEngineInterface
return [];
}
}
private function buildHighlightRules(QueryContext $context)
{
$highlighted_fields = [];
foreach ($context->getHighlightedFields() as $field) {
switch ($field->getType()) {
case FieldMapping::TYPE_STRING:
$index_field = $field->getIndexField();
$raw_index_field = $field->getIndexField(true);
$highlighted_fields[$index_field . ".light"] = [
// Requires calling Mapping::enableTermVectors() on this field mapping
// 'matched_fields' => [$index_field, $raw_index_field],
'type' => 'fvh',
];
break;
case FieldMapping::TYPE_FLOAT:
case FieldMapping::TYPE_DOUBLE:
case FieldMapping::TYPE_INTEGER:
case FieldMapping::TYPE_LONG:
case FieldMapping::TYPE_SHORT:
case FieldMapping::TYPE_BYTE:
continue;
case FieldMapping::TYPE_DATE:
default:
continue;
}
}
return [
'pre_tags' => ['[[em]]'],
'post_tags' => ['[[/em]]'],
'order' => 'score',
'fields' => $highlighted_fields
];
}
private function getAggregationQueryParams(SearchEngineOptions $options)
{
$aggs = [];
// technical aggregates (enable + optional limit)
foreach (ElasticsearchOptions::getAggregableTechnicalFields() as $k => $f) {
$size = $this->options->getAggregableFieldLimit($k);
if ($size !== databox_field::FACET_DISABLED) {
if ($size === databox_field::FACET_NO_LIMIT) {
$size = ESField::FACET_NO_LIMIT;
}
$agg = [
'terms' => [
'field' => $f['field'],
'size' => $size
]
];
$aggs[$k] = $agg;
}
}
// fields aggregates
$structure = $this->context_factory->getLimitedStructure($options);
foreach ($structure->getFacetFields() as $name => $field) {
// 2015-05-26 (mdarse) Removed databox filtering.
// It was already done by the ACL filter in the query scope, so no
// document that shouldn't be displayed can go this far.
$agg = [
'terms' => [
'field' => $field->getIndexField(true),
'size' => $field->getFacetValuesLimit()
]
];
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
}
return $aggs;
}
/**
* {@inheritdoc}
*/
public function autocomplete($query, SearchEngineOptions $options)
{
$params = $this->createCompletionParams($query, $options);
$res = $this->client->suggest($params);
$ret = [
'text' => [],
'byField' => []
];
foreach (array_keys($params['body']) as $fname) {
$t = [];
foreach ($res[$fname] as $suggest) { // don't know why there is a sub-array level
foreach ($suggest['options'] as $option) {
$text = $option['text'];
if (!in_array($text, $ret['text'])) {
$ret['text'][] = $text;
}
$t[] = [
'label' => $text,
'query' => $fname . ':' . $text
];
}
}
if (!empty($t)) {
$ret['byField'][$fname] = $t;
}
}
return $ret;
}
private function createCompletionParams($query, SearchEngineOptions $options)
{
$body = [];
$context = [
'record_type' => $options->getSearchType() === SearchEngineOptions::RECORD_RECORD ?
SearchEngineInterface::GEM_TYPE_RECORD : SearchEngineInterface::GEM_TYPE_STORY
];
$base_ids = $options->getBasesIds();
if (count($base_ids) > 0) {
$context['base_id'] = $base_ids;
}
$search_context = $this->context_factory->createContext($options);
$fields = $search_context->getUnrestrictedFields();
foreach ($fields as $field) {
if ($field->getType() == FieldMapping::TYPE_STRING) {
$k = '' . $field->getName();
$body[$k] = [
'text' => $query,
'completion' => [
'field' => "caption." . $field->getName() . ".suggest",
'context' => &$context
]
];
}
}
return [
'index' => $this->indexName,
'body' => $body
];
}
/**
* {@inheritdoc}
*/
public function resetCache()
{
}
/**
* {@inheritdoc}
*/
public function clearCache()
{
}
/**
* {@inheritdoc}
*/
public function clearAllCache(\DateTime $date = null)
{
}
}

View File

@@ -32,7 +32,10 @@ class ElasticsearchRecordHydrator
if (substr($key, 0, strlen($prefix)) == $prefix) {
$key = substr($key, strlen($prefix));
}
$highlight[$key] = $value;
if (substr($key, -6) == '.light') {
$key = substr($key, 0, strlen($key) - 6);
$highlight[$key] = $value;
}
}
$record = new ElasticsearchRecord();

View File

@@ -47,12 +47,36 @@ class PhraseanetExtension extends \Twig_Extension
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_order', array($this, 'getCaptionFieldOrder')),
new \Twig_SimpleFunction('flag_slugify', array(Flag::class, 'normalizeName')),
);
}
/**
* 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 '';
}
public function getCaptionField(RecordInterface $record, $field, $value)
{
if ($record instanceof ElasticsearchRecord) {
@@ -99,6 +123,31 @@ class PhraseanetExtension extends \Twig_Extension
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 = [];
@@ -132,24 +181,6 @@ class PhraseanetExtension extends \Twig_Extension
return $recordStatuses;
}
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;
}
/**
* 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 ?
@@ -177,6 +208,24 @@ class PhraseanetExtension extends \Twig_Extension
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))) {
@@ -242,11 +291,6 @@ class PhraseanetExtension extends \Twig_Extension
return $this->getSubdefUrl($record, 'thumbnail');
}
public function getThumbnailGifUrl(RecordInterface $record)
{
return $this->getSubdefUrl($record, 'thumbnailgif');
}
public function getSubdefUrl(RecordInterface $record, $subdefName)
{
/** @var StaticMode $staticMode */
@@ -279,6 +323,11 @@ class PhraseanetExtension extends \Twig_Extension
return $path;
}
public function getThumbnailGifUrl(RecordInterface $record)
{
return $this->getSubdefUrl($record, 'thumbnailgif');
}
public function getSubdefSize(RecordInterface $record, $subdefName)
{
$ret = null;
@@ -325,29 +374,4 @@ class PhraseanetExtension extends \Twig_Extension
{
return 'phraseanet';
}
/**
* @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,
];
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2018-04-16T07:02:10Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<file date="2018-05-23T10:45:26Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -10,8 +10,8 @@
<source>Please provide the same passwords.</source>
<target state="translated">Bitte geben Sie diesselbe Passwörter ein.</target>
<jms:reference-file line="44">Form/Login/PhraseaRecoverPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
<jms:reference-file line="36">Form/Login/PhraseaRenewPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
</trans-unit>
<trans-unit id="90b8c9717bb7ed061dbf20fe1986c8b8593d43d4" resname="The token provided is not valid anymore" approved="yes">
<source>The token provided is not valid anymore</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2018-04-16T07:02:50Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<file date="2018-05-23T10:47:03Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -10,8 +10,8 @@
<source>Please provide the same passwords.</source>
<target state="translated">Please provide the same passwords.</target>
<jms:reference-file line="44">Form/Login/PhraseaRecoverPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
<jms:reference-file line="36">Form/Login/PhraseaRenewPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
</trans-unit>
<trans-unit id="90b8c9717bb7ed061dbf20fe1986c8b8593d43d4" resname="The token provided is not valid anymore" approved="yes">
<source>The token provided is not valid anymore</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2018-04-16T07:03:37Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<file date="2018-05-23T10:48:47Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -10,8 +10,8 @@
<source>Please provide the same passwords.</source>
<target state="translated">Veuillez indiquer des mots de passe identiques.</target>
<jms:reference-file line="44">Form/Login/PhraseaRecoverPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
<jms:reference-file line="36">Form/Login/PhraseaRenewPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
</trans-unit>
<trans-unit id="90b8c9717bb7ed061dbf20fe1986c8b8593d43d4" resname="The token provided is not valid anymore" approved="yes">
<source>The token provided is not valid anymore</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2018-04-16T07:04:28Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
<file date="2018-05-23T10:50:41Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -10,8 +10,8 @@
<source>Please provide the same passwords.</source>
<target state="new">Please provide the same passwords.</target>
<jms:reference-file line="44">Form/Login/PhraseaRecoverPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
<jms:reference-file line="36">Form/Login/PhraseaRenewPasswordForm.php</jms:reference-file>
<jms:reference-file line="49">Form/Login/PhraseaRegisterForm.php</jms:reference-file>
</trans-unit>
<trans-unit id="90b8c9717bb7ed061dbf20fe1986c8b8593d43d4" resname="The token provided is not valid anymore">
<source>The token provided is not valid anymore</source>

View File

@@ -55,7 +55,7 @@ $(function () {
$('#fileupload').fileupload({
dataType: 'html',
add: function(e, data) {
if( ! /(\.|\/)(csv|rtf)$/i.test(data.files[0].type)) {
if( ! /(\.|\/)(csv|rtf)$/i.test(data.files[0].name)) {
{% set supported_file_types = ['csv', 'rtf']|join(' | ') %}
alert("{{ 'Invalid file type, only (%supported_file_types%) file formats are supported' | trans({'%supported_file_types%' : supported_file_types}) | e('js') }}");

View File

@@ -93,9 +93,9 @@
{% set terms = [] %}
{% for data in field.values %}
{% if data.from_thesaurus and bounceable %}
{% set value = data.value|e|bounce(field.name, data.qjs, field.sbas_id) %}
{% set value = data.value|e|bounce(field.name, data.qjs, field.sbas_id)|parseColor %}
{% else %}
{% set value = data.value|e %}
{% set value = data.value|e|parseColor %}
{% endif %}
{% set terms = [value]|merge(terms) %}
{% endfor %}
@@ -126,10 +126,10 @@
{% macro caption(record, can_see_business, display_exif, limitedWidth = false) %}
<dl class="{% if limitedWidth %}{% else %}dl-horizontal{% endif %}">
{% for field in record.get_caption().get_highlight_fields(null, can_see_business) %}
<dt>{{ field.label_name }}</dt>
<dd>{{ _self.caption_value(field, bounceable|default(true))|highlight|linkify }}</dd>
{% endfor %}
{% for name, value in record.getCaption(caption_field_order(record, can_see_business)) %}
<dt>{{ caption_field_label(record, name) }}</dt>
<dd>{{ caption_field(record, name, value)|e|highlight|linkify|parseColor }}</dd>
{% endfor %}
</dl>
{% if display_exif|default(true) and app.getAuthenticator().user is not none and user_setting('technical_display') == 'group' %}
<hr/>

View File

@@ -128,7 +128,7 @@
{% else %}
<a target="_blank" href="{{ path('account') }}" title="{{ 'login:: Mon compte' | trans }}">
<span>
{{app.getAuthenticatedUser().getLogin()}}
{{ app.getAuthenticatedUser().getDisplayName() }}
</span>
</a>
{% endif %}

View File

@@ -18,6 +18,10 @@
<input type="radio" name="lay" value="previewCaptionTdm" id="RADI_PRE_TDM" />
{{ 'print:: image de choix et description avec planche contact' | trans }}
</label>
<label for="RADI_CAP" class="radio">
<input type="radio" name="lay" value="caption" id="RADI_CAP" />
{{ 'print:: description' | trans }}
</label>
</div>
{% endif %}
{% if printer.get_count_thumbnail() > 0 %}

View File

@@ -24,7 +24,7 @@
{% set can_see_business = granted_on_collection(record.baseId, [constant('\\ACL::CANMODIFRECORD')]) %}
<div class="thumb captionTips"
{% if settings.rollover_thumbnail == 'caption' %}tooltipsrc="{{ path('prod_tooltip_caption', { 'sbas_id' : record.databoxId, 'record_id' : record.recordId, 'context' : 'answer', 'number' : record.position|default(0) }) }}"{% endif %}
{% if settings.rollover_thumbnail == 'caption' %}title="{{ macro.caption(record, can_see_business, false) | e }}"{% endif %}
{% if settings.rollover_thumbnail == 'preview' %}tooltipsrc="{{ path('prod_tooltip_preview', { 'sbas_id' : record.databoxId, 'record_id' : record.recordId }) }}"{% endif %}
style="height:{{ settings.images_size }}px; z-index:90;">
<div class="doc_infos">