mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-07 18:14:35 +00:00

* field with label on print * option to hide record information in preview when print * add column printable * add color picker * patch on 4 1 6 cr4 * update locale * bump version to 4.1.6-rc4 * fix bloc info color * font size bloc info * some fix * Fallback to thumbnail when chosen subdefinition is not present or not printable
1617 lines
50 KiB
PHP
1617 lines
50 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of Phraseanet
|
|
*
|
|
* (c) 2005-2016 Alchemy
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
use Alchemy\Phrasea\Application;
|
|
use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry;
|
|
use Alchemy\Phrasea\Core\Connection\ConnectionSettings;
|
|
use Alchemy\Phrasea\Core\PhraseaTokens;
|
|
use Alchemy\Phrasea\Core\Thumbnail\ThumbnailedElement;
|
|
use Alchemy\Phrasea\Core\Version\DataboxVersionRepository;
|
|
use Alchemy\Phrasea\Databox\DataboxRepository;
|
|
use Alchemy\Phrasea\Databox\Record\RecordRepository;
|
|
use Alchemy\Phrasea\Databox\SubdefGroup;
|
|
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
|
use Alchemy\Phrasea\Model\Entities\User;
|
|
use Alchemy\Phrasea\Status\StatusStructure;
|
|
use Alchemy\Phrasea\Status\StatusStructureFactory;
|
|
use Doctrine\DBAL\Connection;
|
|
use Doctrine\DBAL\Driver\Statement;
|
|
use Symfony\Component\HttpFoundation\File\File;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
use Symfony\Component\Translation\TranslatorInterface;
|
|
|
|
use Alchemy\Phrasea\Core\Event\Databox\DataboxEvents;
|
|
use Alchemy\Phrasea\Core\Event\Databox\CreatedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\DeletedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\MountedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\ReindexAskedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\StructureChangedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\ThesaurusChangedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\TouChangedEvent;
|
|
use Alchemy\Phrasea\Core\Event\Databox\UnmountedEvent;
|
|
|
|
|
|
class databox extends base implements ThumbnailedElement
|
|
{
|
|
|
|
const BASE_TYPE = self::DATA_BOX;
|
|
const CACHE_META_STRUCT = 'meta_struct';
|
|
const CACHE_THESAURUS = 'thesaurus';
|
|
const CACHE_COLLECTIONS = 'collections';
|
|
const CACHE_STRUCTURE = 'structure';
|
|
const PIC_PDF = 'logopdf';
|
|
const CACHE_CGUS = 'cgus';
|
|
|
|
/** @var array */
|
|
protected static $_xpath_thesaurus = [];
|
|
/** @var array */
|
|
protected static $_dom_thesaurus = [];
|
|
/** @var array */
|
|
protected static $_thesaurus = [];
|
|
|
|
/** @var SimpleXMLElement */
|
|
protected static $_sxml_thesaurus = [];
|
|
|
|
/**
|
|
* @param Application $app
|
|
* @param Connection $databoxConnection
|
|
* @param SplFileInfo $template
|
|
* @return databox
|
|
* @throws \Doctrine\DBAL\DBALException
|
|
*/
|
|
public static function create(Application $app, Connection $databoxConnection, \SplFileInfo $template)
|
|
{
|
|
$rp = $template->getRealPath();
|
|
if (!$rp || !file_exists($rp)) {
|
|
throw new \InvalidArgumentException(sprintf('Databox template "%s" not found.', $template->getFilename()));
|
|
}
|
|
|
|
$host = $databoxConnection->getHost();
|
|
$port = $databoxConnection->getPort();
|
|
$dbname = $databoxConnection->getDatabase();
|
|
$user = $databoxConnection->getUsername();
|
|
$password = $databoxConnection->getPassword();
|
|
|
|
$appbox = $app->getApplicationBox();
|
|
|
|
try {
|
|
$sql = 'CREATE DATABASE `' . $dbname . '` CHARACTER SET utf8 COLLATE utf8_unicode_ci';
|
|
$stmt = $databoxConnection->prepare($sql);
|
|
$stmt->execute();
|
|
$stmt->closeCursor();
|
|
} catch (\Exception $e) {
|
|
|
|
}
|
|
|
|
$sql = 'USE `' . $dbname . '`';
|
|
$stmt = $databoxConnection->prepare($sql);
|
|
$stmt->execute();
|
|
$stmt->closeCursor();
|
|
|
|
$app['orm.add']([
|
|
'host' => $host,
|
|
'port' => $port,
|
|
'dbname' => $dbname,
|
|
'user' => $user,
|
|
'password' => $password
|
|
]);
|
|
|
|
phrasea::reset_sbasDatas($app['phraseanet.appbox']);
|
|
|
|
/** @var DataboxRepository $databoxRepository */
|
|
$databoxRepository = $app['repo.databoxes'];
|
|
$databox = $databoxRepository->create($host, $port, $user, $password, $dbname);
|
|
|
|
$appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES);
|
|
|
|
$databox->insert_datas();
|
|
$databox->setNewStructure(
|
|
$template, $app['conf']->get(['main', 'storage', 'subdefs'])
|
|
);
|
|
|
|
$app['dispatcher']->dispatch(DataboxEvents::CREATED, new CreatedEvent($databox));
|
|
|
|
return $databox;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param Application $app
|
|
* @param string $host
|
|
* @param int $port
|
|
* @param string $user
|
|
* @param string $password
|
|
* @param string $dbname
|
|
* @return databox
|
|
*/
|
|
public static function mount(Application $app, $host, $port, $user, $password, $dbname)
|
|
{
|
|
$app['db.provider']([
|
|
'host' => $host,
|
|
'port' => $port,
|
|
'user' => $user,
|
|
'password' => $password,
|
|
'dbname' => $dbname,
|
|
])->connect();
|
|
|
|
/** @var DataboxRepository $databoxRepository */
|
|
$databoxRepository = $app['repo.databoxes'];
|
|
$databox = $databoxRepository->mount($host, $port, $user, $password, $dbname);
|
|
|
|
$databox->delete_data_from_cache(databox::CACHE_COLLECTIONS);
|
|
$app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
|
|
|
|
phrasea::reset_sbasDatas($app['phraseanet.appbox']);
|
|
cache_databox::update($app, $databox->get_sbas_id(), 'structure');
|
|
|
|
$app['dispatcher']->dispatch(DataboxEvents::MOUNTED, new MountedEvent($databox));
|
|
|
|
return $databox;
|
|
}
|
|
|
|
public static function get_available_dcfields()
|
|
{
|
|
return [
|
|
databox_Field_DCESAbstract::Contributor => new databox_Field_DCES_Contributor(),
|
|
databox_Field_DCESAbstract::Coverage => new databox_Field_DCES_Coverage(),
|
|
databox_Field_DCESAbstract::Creator => new databox_Field_DCES_Creator(),
|
|
databox_Field_DCESAbstract::Date => new databox_Field_DCES_Date(),
|
|
databox_Field_DCESAbstract::Description => new databox_Field_DCES_Description(),
|
|
databox_Field_DCESAbstract::Format => new databox_Field_DCES_Format(),
|
|
databox_Field_DCESAbstract::Identifier => new databox_Field_DCES_Identifier(),
|
|
databox_Field_DCESAbstract::Language => new databox_Field_DCES_Language(),
|
|
databox_Field_DCESAbstract::Publisher => new databox_Field_DCES_Publisher(),
|
|
databox_Field_DCESAbstract::Relation => new databox_Field_DCES_Relation(),
|
|
databox_Field_DCESAbstract::Rights => new databox_Field_DCES_Rights(),
|
|
databox_Field_DCESAbstract::Source => new databox_Field_DCES_Source(),
|
|
databox_Field_DCESAbstract::Subject => new databox_Field_DCES_Subject(),
|
|
databox_Field_DCESAbstract::Title => new databox_Field_DCES_Title(),
|
|
databox_Field_DCESAbstract::Type => new databox_Field_DCES_Type()
|
|
];
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param int $sbas_id
|
|
* @return string
|
|
*/
|
|
public static function getPrintLogo($sbas_id)
|
|
{
|
|
$out = '';
|
|
if (is_file(($filename = __DIR__ . '/../../config/minilogos/'.\databox::PIC_PDF.'_' . $sbas_id . '.jpg')))
|
|
$out = file_get_contents($filename);
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* @param TranslatorInterface $translator
|
|
* @param string $structure
|
|
* @return Array
|
|
*/
|
|
public static function get_structure_errors(TranslatorInterface $translator, $structure)
|
|
{
|
|
$sx_structure = simplexml_load_string($structure);
|
|
|
|
$subdefgroup = $sx_structure->subdefs[0];
|
|
$AvSubdefs = [];
|
|
|
|
$errors = [];
|
|
|
|
foreach ($subdefgroup as $k => $subdefs) {
|
|
$subdefgroup_name = trim((string) $subdefs->attributes()->name);
|
|
|
|
if ($subdefgroup_name == '') {
|
|
$errors[] = $translator->trans('ERREUR : TOUTES LES BALISES subdefgroup necessitent un attribut name');
|
|
continue;
|
|
}
|
|
|
|
if ( ! isset($AvSubdefs[$subdefgroup_name]))
|
|
$AvSubdefs[$subdefgroup_name] = [];
|
|
|
|
foreach ($subdefs as $sd) {
|
|
$sd_name = trim(mb_strtolower((string) $sd->attributes()->name));
|
|
$sd_class = trim(mb_strtolower((string) $sd->attributes()->class));
|
|
if ($sd_name == '' || isset($AvSubdefs[$subdefgroup_name][$sd_name])) {
|
|
$errors[] = $translator->trans('ERREUR : Les name de subdef sont uniques par groupe de subdefs et necessaire');
|
|
continue;
|
|
}
|
|
if ( ! in_array($sd_class, ['thumbnail', 'preview', 'document'])) {
|
|
$errors[] = $translator->trans('ERREUR : La classe de subdef est necessaire et egal a "thumbnail","preview" ou "document"');
|
|
continue;
|
|
}
|
|
$AvSubdefs[$subdefgroup_name][$sd_name] = $sd;
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
public static function purge()
|
|
{
|
|
self::$_xpath_thesaurus = self::$_dom_thesaurus = self::$_thesaurus = self::$_sxml_thesaurus = [];
|
|
}
|
|
|
|
/** @var int */
|
|
protected $id;
|
|
/** @var string */
|
|
protected $structure;
|
|
/** @var array */
|
|
protected $_xpath_structure;
|
|
/** @var DOMDocument */
|
|
protected $_dom_structure;
|
|
/** @var DOMDocument */
|
|
protected $_dom_cterms;
|
|
/** @var SimpleXMLElement */
|
|
protected $_sxml_structure;
|
|
/** @var databox_descriptionStructure */
|
|
protected $meta_struct;
|
|
/** @var databox_subdefsStructure */
|
|
protected $subdef_struct;
|
|
protected $thesaurus;
|
|
protected $cterms;
|
|
protected $cgus;
|
|
/** @var DataboxRepository */
|
|
private $databoxRepository;
|
|
/** @var RecordRepository */
|
|
private $recordRepository;
|
|
/** @var string[] */
|
|
private $labels = [];
|
|
/** @var int */
|
|
private $ord;
|
|
/** @var string */
|
|
private $viewname;
|
|
|
|
/**
|
|
* @param Application $app
|
|
* @param int $sbas_id
|
|
* @param DataboxRepository $databoxRepository
|
|
* @param array $row
|
|
*/
|
|
public function __construct(Application $app, $sbas_id, DataboxRepository $databoxRepository, array $row)
|
|
{
|
|
assert(is_int($sbas_id));
|
|
assert($sbas_id > 0);
|
|
|
|
$this->databoxRepository = $databoxRepository;
|
|
$this->id = $sbas_id;
|
|
|
|
$connectionConfigs = phrasea::sbas_params($app);
|
|
|
|
if (! isset($connectionConfigs[$sbas_id])) {
|
|
throw new NotFoundHttpException(sprintf('databox %d not found', $sbas_id));
|
|
}
|
|
|
|
$connectionConfig = $connectionConfigs[$sbas_id];
|
|
$connection = $app['db.provider']($connectionConfig);
|
|
|
|
$connectionSettings = new ConnectionSettings(
|
|
$connectionConfig['host'],
|
|
$connectionConfig['port'],
|
|
$connectionConfig['dbname'],
|
|
$connectionConfig['user'],
|
|
$connectionConfig['password']
|
|
);
|
|
|
|
$versionRepository = new DataboxVersionRepository($connection);
|
|
|
|
parent::__construct($app, $connection, $connectionSettings, $versionRepository);
|
|
|
|
$this->loadFromRow($row);
|
|
}
|
|
|
|
public function setNewStructure(\SplFileInfo $data_template, $path_doc)
|
|
{
|
|
if ( ! file_exists($data_template->getPathname())) {
|
|
throw new \InvalidArgumentException(sprintf('File %s does not exists'));
|
|
}
|
|
|
|
$contents = file_get_contents($data_template->getPathname());
|
|
|
|
$contents = str_replace(
|
|
["{{basename}}", "{{datapathnoweb}}"]
|
|
, [$this->connectionSettings->getDatabaseName(), rtrim($path_doc, '/').'/']
|
|
, $contents
|
|
);
|
|
|
|
$dom_doc = new DOMDocument();
|
|
$dom_doc->loadXML($contents);
|
|
$this->saveStructure($dom_doc);
|
|
|
|
$this->feed_meta_fields();
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param DOMDocument $dom_struct
|
|
* @return databox
|
|
*/
|
|
public function saveStructure(DOMDocument $dom_struct)
|
|
{
|
|
$old_structure = $this->get_dom_structure();
|
|
|
|
$dom_struct->documentElement
|
|
->setAttribute("modification_date", $now = date("YmdHis"));
|
|
|
|
$sql = "UPDATE pref SET value= :structure, updated_on= :now WHERE prop='structure'";
|
|
|
|
$this->structure = $dom_struct->saveXML();
|
|
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute(
|
|
[
|
|
':structure' => $this->structure,
|
|
':now' => $now
|
|
]
|
|
);
|
|
$stmt->closeCursor();
|
|
|
|
$this->_sxml_structure = $this->_dom_structure = $this->_xpath_structure = null;
|
|
|
|
$this->meta_struct = null;
|
|
|
|
$this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
|
|
$this->delete_data_from_cache(self::CACHE_STRUCTURE);
|
|
$this->delete_data_from_cache(self::CACHE_META_STRUCT);
|
|
|
|
cache_databox::update($this->app, $this->id, 'structure');
|
|
|
|
$this->databoxRepository->save($this);
|
|
|
|
$this->app['dispatcher']->dispatch(
|
|
DataboxEvents::STRUCTURE_CHANGED,
|
|
new StructureChangedEvent(
|
|
$this,
|
|
[
|
|
'dom_before'=>$old_structure
|
|
]
|
|
)
|
|
);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return DOMDocument
|
|
*/
|
|
public function get_dom_structure()
|
|
{
|
|
if ($this->_dom_structure) {
|
|
return $this->_dom_structure;
|
|
}
|
|
|
|
$structure = $this->get_structure();
|
|
|
|
$dom = new DOMDocument();
|
|
|
|
$dom->standalone = true;
|
|
$dom->preserveWhiteSpace = false;
|
|
$dom->formatOutput = true;
|
|
|
|
if ($structure && $dom->loadXML($structure) !== false)
|
|
$this->_dom_structure = $dom;
|
|
else
|
|
$this->_dom_structure = false;
|
|
|
|
return $this->_dom_structure;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function get_structure()
|
|
{
|
|
if ($this->structure) {
|
|
return $this->structure;
|
|
}
|
|
|
|
$this->structure = $this->retrieve_structure();
|
|
|
|
return $this->structure;
|
|
}
|
|
|
|
public function feed_meta_fields()
|
|
{
|
|
$sxe = $this->get_sxml_structure();
|
|
|
|
foreach ($sxe->description->children() as $fname => $field) {
|
|
$dom_struct = $this->get_dom_structure();
|
|
$xp_struct = $this->get_xpath_structure();
|
|
$fname = (string) $fname;
|
|
$src = trim(isset($field['src']) ? str_replace('/rdf:RDF/rdf:Description/', '', $field['src']) : '');
|
|
|
|
$meta_id = isset($field['meta_id']) ? $field['meta_id'] : null;
|
|
if ( ! is_null($meta_id))
|
|
continue;
|
|
|
|
$nodes = $xp_struct->query('/record/description/' . $fname);
|
|
if ($nodes->length > 0) {
|
|
$nodes->item(0)->parentNode->removeChild($nodes->item(0));
|
|
}
|
|
$this->saveStructure($dom_struct);
|
|
|
|
$type = isset($field['type']) ? $field['type'] : 'string';
|
|
$type = in_array($type
|
|
, [
|
|
databox_field::TYPE_DATE
|
|
, databox_field::TYPE_NUMBER
|
|
, databox_field::TYPE_STRING
|
|
]
|
|
) ? $type : databox_field::TYPE_STRING;
|
|
|
|
$multi = isset($field['multi']) ? (Boolean) (string) $field['multi'] : false;
|
|
|
|
$meta_struct_field = databox_field::create($this->app, $this, $fname);
|
|
$meta_struct_field
|
|
->set_multi($multi)
|
|
->set_readonly(isset($field['readonly']) ? (string) $field['readonly'] : 0)
|
|
->set_indexable(isset($field['index']) ? (string) $field['index'] : '1')
|
|
->set_separator(isset($field['separator']) ? (string) $field['separator'] : '')
|
|
->set_required((isset($field['required']) && (string) $field['required'] == 1))
|
|
->set_business((isset($field['business']) && (string) $field['business'] == 1))
|
|
->set_aggregable((isset($field['aggregable']) ? (string) $field['aggregable'] : 0))
|
|
->set_type($type)
|
|
->set_tbranch(isset($field['tbranch']) ? (string) $field['tbranch'] : '')
|
|
->set_generate_cterms((isset($field['generate_cterms']) && (string) $field['generate_cterms'] == 1))
|
|
->set_gui_editable((!isset($field['gui_editable']) || (isset($field['gui_editable']) && (string) $field['gui_editable'] == 1)))
|
|
->set_gui_visible((!isset($field['gui_visible']) || (isset($field['gui_visible']) && (string) $field['gui_visible'] == 1)))
|
|
->set_printable((!isset($field['printable']) || (isset($field['printable']) && (string) $field['printable'] == 1)))
|
|
->set_thumbtitle(isset($field['thumbtitle']) ? (string) $field['thumbtitle'] : (isset($field['thumbTitle']) ? $field['thumbTitle'] : '0'))
|
|
->set_report(isset($field['report']) ? (string) $field['report'] : '1')
|
|
->save();
|
|
|
|
try {
|
|
$meta_struct_field->set_tag(\databox_field::loadClassFromTagName($src))->save();
|
|
} catch (\Exception $e) {
|
|
}
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return SimpleXMLElement
|
|
*/
|
|
public function get_sxml_structure()
|
|
{
|
|
if ($this->_sxml_structure) {
|
|
return $this->_sxml_structure;
|
|
}
|
|
|
|
$structure = $this->get_structure();
|
|
|
|
if ($structure && false !== $tmp = simplexml_load_string($structure))
|
|
$this->_sxml_structure = $tmp;
|
|
else
|
|
$this->_sxml_structure = false;
|
|
|
|
return $this->_sxml_structure;
|
|
}
|
|
|
|
/**
|
|
* @return DOMXpath
|
|
*/
|
|
public function get_xpath_structure()
|
|
{
|
|
if ($this->_xpath_structure) {
|
|
return $this->_xpath_structure;
|
|
}
|
|
|
|
$dom_doc = $this->get_dom_structure();
|
|
|
|
if ($dom_doc && ($tmp = new DOMXpath($dom_doc)) !== false)
|
|
$this->_xpath_structure = $tmp;
|
|
else
|
|
$this->_xpath_structure = false;
|
|
|
|
return $this->_xpath_structure;
|
|
}
|
|
|
|
/**
|
|
* @return RecordRepository
|
|
*/
|
|
public function getRecordRepository()
|
|
{
|
|
if (null === $this->recordRepository) {
|
|
$this->recordRepository = $this->app['repo.records.factory']($this);
|
|
}
|
|
|
|
return $this->recordRepository;
|
|
}
|
|
|
|
public function get_ord()
|
|
{
|
|
return $this->ord;
|
|
}
|
|
|
|
public function getRootIdentifier()
|
|
{
|
|
return $this->get_sbas_id();
|
|
}
|
|
|
|
/**
|
|
* Returns current sbas_id
|
|
*
|
|
* @return int
|
|
*/
|
|
public function get_sbas_id()
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
public function updateThumbnail($thumbnailType, File $file = null)
|
|
{
|
|
$this->delete_data_from_cache('printLogo');
|
|
}
|
|
|
|
public function delete_data_from_cache($option = null)
|
|
{
|
|
switch ($option) {
|
|
case self::CACHE_CGUS:
|
|
$this->cgus = null;
|
|
break;
|
|
case self::CACHE_META_STRUCT:
|
|
$this->meta_struct = null;
|
|
break;
|
|
case self::CACHE_STRUCTURE:
|
|
$this->_dom_structure = $this->_xpath_structure = $this->structure = $this->_sxml_structure = null;
|
|
break;
|
|
case self::CACHE_THESAURUS:
|
|
$this->thesaurus = null;
|
|
unset(self::$_dom_thesaurus[$this->id]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
parent::delete_data_from_cache($option);
|
|
}
|
|
|
|
/*
|
|
* trivial cache to speed-up get_collections() which does sql
|
|
*/
|
|
private $_collection_unique_ids = null;
|
|
private $_collections = null;
|
|
|
|
public function clearCache($what)
|
|
{
|
|
switch($what) {
|
|
case self::CACHE_COLLECTIONS:
|
|
$this->_collection_unique_ids = $this->_collections = null;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return int[]
|
|
*/
|
|
public function get_collection_unique_ids()
|
|
{
|
|
if($this->_collection_unique_ids === null) {
|
|
$this->_collection_unique_ids = [];
|
|
|
|
foreach ($this->get_collections() as $collection) {
|
|
$this->_collection_unique_ids[] = $collection->get_base_id();
|
|
}
|
|
}
|
|
|
|
return $this->_collection_unique_ids;
|
|
}
|
|
|
|
/**
|
|
* @return collection[]
|
|
*/
|
|
public function get_collections()
|
|
{
|
|
if($this->_collections === null) {
|
|
/** @var CollectionRepositoryRegistry $repositoryRegistry */
|
|
$repositoryRegistry = $this->app['repo.collections-registry'];
|
|
$repository = $repositoryRegistry->getRepositoryByDatabox($this->get_sbas_id());
|
|
|
|
$this->_collections = array_filter($repository->findAll(), function (collection $collection) {
|
|
return $collection->is_active();
|
|
});
|
|
}
|
|
|
|
return $this->_collections;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return collection|null
|
|
*/
|
|
public function getTrashCollection()
|
|
{
|
|
foreach($this->get_collections() as $collection) {
|
|
if($collection->get_name() === '_TRASH_') {
|
|
return $collection;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param int $record_id
|
|
* @param int $number
|
|
* @return record_adapter
|
|
*/
|
|
public function get_record($record_id, $number = null)
|
|
{
|
|
return new record_adapter($this->app, $this->id, $record_id, $number);
|
|
}
|
|
|
|
public function get_label($code, $substitute = true)
|
|
{
|
|
if (!array_key_exists($code, $this->labels)) {
|
|
throw new InvalidArgumentException(sprintf('Code %s is not defined', $code));
|
|
}
|
|
|
|
if ($substitute) {
|
|
return isset($this->labels[$code]) ? $this->labels[$code] : $this->get_viewname();
|
|
} else {
|
|
return $this->labels[$code];
|
|
}
|
|
}
|
|
|
|
public function get_viewname()
|
|
{
|
|
return $this->viewname ? : $this->connectionSettings->getDatabaseName();
|
|
}
|
|
|
|
public function set_viewname($viewname)
|
|
{
|
|
$sql = 'UPDATE sbas SET viewname = :viewname WHERE sbas_id = :sbas_id';
|
|
|
|
$stmt = $this->get_appbox()->get_connection()->prepare($sql);
|
|
$stmt->execute([':viewname' => $viewname, ':sbas_id' => $this->id]);
|
|
$stmt->closeCursor();
|
|
|
|
$this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
|
|
cache_databox::update($this->app, $this->id, 'structure');
|
|
|
|
$this->viewname = $viewname;
|
|
$this->databoxRepository->save($this);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return appbox
|
|
*/
|
|
public function get_appbox()
|
|
{
|
|
return $this->app->getApplicationBox();
|
|
}
|
|
|
|
public function set_label($code, $label)
|
|
{
|
|
if (!array_key_exists($code, $this->labels)) {
|
|
throw new InvalidArgumentException(sprintf('Code %s is not defined', $code));
|
|
}
|
|
|
|
$sql = "UPDATE sbas SET label_$code = :label
|
|
WHERE sbas_id = :sbas_id";
|
|
$stmt = $this->get_appbox()->get_connection()->prepare($sql);
|
|
$stmt->execute([':label' => $label, ':sbas_id' => $this->id]);
|
|
$stmt->closeCursor();
|
|
|
|
$this->labels[$code] = $label;
|
|
|
|
$this->databoxRepository->save($this);
|
|
|
|
phrasea::reset_sbasDatas($this->app['phraseanet.appbox']);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return StatusStructure
|
|
*/
|
|
public function getStatusStructure()
|
|
{
|
|
/** @var StatusStructureFactory $structureFactory */
|
|
$structureFactory = $this->app['factory.status-structure'];
|
|
|
|
return $structureFactory->getStructure($this);
|
|
}
|
|
|
|
public function get_record_details($sort)
|
|
{
|
|
$sql = "SELECT record.coll_id, ISNULL(coll.coll_id) AS lostcoll,
|
|
COALESCE(asciiname, CONCAT('_',record.coll_id)) AS asciiname, name,
|
|
SUM(1) AS n, SUM(size) AS siz FROM (record, subdef)
|
|
LEFT JOIN coll ON record.coll_id=coll.coll_id
|
|
WHERE record.record_id = subdef.record_id
|
|
GROUP BY record.coll_id, name
|
|
UNION
|
|
SELECT coll.coll_id, 0, asciiname, '_' AS name, 0 AS n, 0 AS siz
|
|
FROM coll LEFT JOIN record ON record.coll_id=coll.coll_id
|
|
WHERE ISNULL(record.coll_id)
|
|
GROUP BY record.coll_id, name";
|
|
|
|
if ($sort == "obj") {
|
|
$sortk1 = "name";
|
|
$sortk2 = "asciiname";
|
|
} else {
|
|
$sortk1 = "asciiname";
|
|
$sortk2 = "name";
|
|
}
|
|
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
foreach ($rs as $rowbas) {
|
|
if ( ! isset($trows[$rowbas[$sortk1]]))
|
|
$trows[$rowbas[$sortk1]] = [];
|
|
$trows[$rowbas[$sortk1]][$rowbas[$sortk2]] = [
|
|
"coll_id" => $rowbas["coll_id"],
|
|
"asciiname" => $rowbas["asciiname"],
|
|
"lostcoll" => $rowbas["lostcoll"],
|
|
"name" => $rowbas["name"],
|
|
"n" => $rowbas["n"],
|
|
"siz" => $rowbas["siz"]
|
|
];
|
|
}
|
|
|
|
ksort($trows);
|
|
foreach ($trows as $kgrp => $vgrp)
|
|
ksort($trows[$kgrp]);
|
|
|
|
return $trows;
|
|
}
|
|
|
|
public function get_record_amount()
|
|
{
|
|
$sql = "SELECT COUNT(record_id) AS n FROM record";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$rowbas = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
$amount = $rowbas ? (int) $rowbas["n"] : null;
|
|
|
|
return $amount;
|
|
}
|
|
|
|
public function get_counts()
|
|
{
|
|
$mask = PhraseaTokens::MAKE_SUBDEF | PhraseaTokens::TO_INDEX | PhraseaTokens::INDEXING; // we only care about those "jetons"
|
|
$sql = "SELECT type, jeton & (".$mask.") AS status, SUM(1) AS n FROM record GROUP BY type, (jeton & ".$mask.")";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
$ret = [
|
|
'records' => 0,
|
|
'records_indexed' => 0, // jetons = 0;0
|
|
'records_to_index' => 0, // jetons = 0;1
|
|
'records_not_indexed' => 0, // jetons = 1;0
|
|
'records_indexing' => 0, // jetons = 1;1
|
|
'subdefs_todo' => [] // by type "image", "video", ...
|
|
];
|
|
foreach ($rs as $row) {
|
|
$ret['records'] += ($n = (int)($row['n']));
|
|
$status = $row['status'];
|
|
switch($status & (PhraseaTokens::TO_INDEX | PhraseaTokens::INDEXING)) {
|
|
case 0:
|
|
$ret['records_indexed'] += $n;
|
|
break;
|
|
case PhraseaTokens::TO_INDEX:
|
|
$ret['records_to_index'] += $n;
|
|
break;
|
|
case PhraseaTokens::INDEXING:
|
|
$ret['records_not_indexed'] += $n;
|
|
break;
|
|
case PhraseaTokens::INDEXING | PhraseaTokens::TO_INDEX:
|
|
$ret['records_indexing'] += $n;
|
|
break;
|
|
}
|
|
if($status & PhraseaTokens::MAKE_SUBDEF) {
|
|
if(!array_key_exists($row['type'], $ret['subdefs_todo'])) {
|
|
$ret['subdefs_todo'][$row['type']] = 0;
|
|
}
|
|
$ret['subdefs_todo'][$row['type']] += $n;
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
public function unmount_databox()
|
|
{
|
|
$old_dbname = $this->get_dbname();
|
|
|
|
foreach ($this->get_collections() as $collection) {
|
|
$collection->unmount();
|
|
}
|
|
|
|
$query = $this->app['phraseanet.user-query'];
|
|
$total = $query->on_sbas_ids([$this->id])
|
|
->include_phantoms(false)
|
|
->include_special_users(true)
|
|
->include_invite(true)
|
|
->include_templates(true)
|
|
->get_total();
|
|
$n = 0;
|
|
while ($n < $total) {
|
|
$results = $query->limit($n, 50)->execute()->get_results();
|
|
foreach ($results as $user) {
|
|
$this->app->getAclForUser($user)->delete_data_from_cache(ACL::CACHE_RIGHTS_SBAS);
|
|
$this->app->getAclForUser($user)->delete_data_from_cache(ACL::CACHE_RIGHTS_BAS);
|
|
$this->app->getAclForUser($user)->delete_injected_rights_sbas($this);
|
|
}
|
|
$n+=50;
|
|
}
|
|
|
|
foreach ($this->app['repo.story-wz']->findByDatabox($this->app, $this) as $story) {
|
|
$this->app['orm.em']->remove($story);
|
|
}
|
|
|
|
foreach ($this->app['repo.basket-elements']->findElementsByDatabox($this) as $element) {
|
|
$this->app['orm.em']->remove($element);
|
|
}
|
|
|
|
$this->app['orm.em']->flush();
|
|
|
|
$params = [':site_id' => $this->app['conf']->get(['main', 'key'])];
|
|
|
|
$sql = 'DELETE FROM clients WHERE site_id = :site_id';
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute($params);
|
|
$stmt->closeCursor();
|
|
|
|
$sql = 'DELETE FROM memcached WHERE site_id = :site_id';
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute($params);
|
|
$stmt->closeCursor();
|
|
|
|
$sql = "DELETE FROM sbas WHERE sbas_id = :sbas_id";
|
|
$stmt = $this->get_appbox()->get_connection()->prepare($sql);
|
|
$stmt->execute([':sbas_id' => $this->id]);
|
|
$stmt->closeCursor();
|
|
|
|
$sql = "DELETE FROM sbasusr WHERE sbas_id = :sbas_id";
|
|
$stmt = $this->get_appbox()->get_connection()->prepare($sql);
|
|
$stmt->execute([':sbas_id' => $this->id]);
|
|
$stmt->closeCursor();
|
|
|
|
$this->databoxRepository->unmount($this);
|
|
$this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
|
|
|
|
$this->app['dispatcher']->dispatch(
|
|
DataboxEvents::UNMOUNTED,
|
|
new UnmountedEvent(
|
|
null,
|
|
[
|
|
'dbname'=>$old_dbname
|
|
]
|
|
)
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
public function get_base_type()
|
|
{
|
|
return self::BASE_TYPE;
|
|
}
|
|
|
|
public function get_cache_key($option = null)
|
|
{
|
|
return 'databox_' . $this->id . '_' . ($option ? $option . '_' : '');
|
|
}
|
|
|
|
/**
|
|
* @return databox_descriptionStructure|databox_field[]
|
|
*/
|
|
public function get_meta_structure()
|
|
{
|
|
if ($this->meta_struct) {
|
|
return $this->meta_struct;
|
|
}
|
|
|
|
/** @var \Alchemy\Phrasea\Databox\Field\DataboxFieldRepository $fieldRepository */
|
|
$fieldRepository = $this->app['repo.fields.factory']($this);
|
|
|
|
$this->meta_struct = new databox_descriptionStructure($fieldRepository->findAll(), $this->app['unicode']);
|
|
|
|
return $this->meta_struct;
|
|
}
|
|
|
|
/**
|
|
* @return databox_subdefsStructure|SubdefGroup[]
|
|
*/
|
|
public function get_subdef_structure()
|
|
{
|
|
if (! $this->subdef_struct) {
|
|
$this->subdef_struct = new databox_subdefsStructure($this, $this->app['translator']);
|
|
}
|
|
|
|
return $this->subdef_struct;
|
|
}
|
|
|
|
public function delete()
|
|
{
|
|
$old_dbname = $this->get_dbname();
|
|
|
|
$sql = 'DROP DATABASE `' . $this->get_dbname() . '`';
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$stmt->closeCursor();
|
|
|
|
$this->get_appbox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
|
|
|
|
$this->databoxRepository->delete($this);
|
|
|
|
$this->app['dispatcher']->dispatch(
|
|
DataboxEvents::DELETED,
|
|
new DeletedEvent(
|
|
null,
|
|
[
|
|
'dbname'=>$old_dbname
|
|
]
|
|
)
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
public function get_serialized_server_info()
|
|
{
|
|
return sprintf("%s@%s:%s (MySQL %s)",
|
|
$this->connectionSettings->getDatabaseName(),
|
|
$this->connectionSettings->getHost(),
|
|
$this->connectionSettings->getPort(),
|
|
$this->get_connection()->getWrappedConnection()->getAttribute(\PDO::ATTR_SERVER_VERSION)
|
|
);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return Array
|
|
*/
|
|
public function get_mountable_colls()
|
|
{
|
|
/** @var Connection $conn */
|
|
$conn = $this->get_appbox()->get_connection();
|
|
$colls = [];
|
|
|
|
$sql = 'SELECT server_coll_id FROM bas WHERE sbas_id = :sbas_id';
|
|
$stmt = $conn->prepare($sql);
|
|
$stmt->execute([':sbas_id' => $this->id]);
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
unset($stmt);
|
|
|
|
foreach ($rs as $row) {
|
|
$colls[] = (int) $row['server_coll_id'];
|
|
}
|
|
|
|
$mountable_colls = [];
|
|
|
|
$builder = $this->get_connection()->createQueryBuilder();
|
|
$builder
|
|
->select('c.coll_id', 'c.asciiname')
|
|
->from('coll', 'c');
|
|
if (count($colls) > 0) {
|
|
$builder
|
|
->where($builder->expr()->notIn('c.coll_id', [':colls']))
|
|
->setParameter('colls', $colls, Connection::PARAM_INT_ARRAY)
|
|
;
|
|
}
|
|
|
|
/** @var Statement $stmt */
|
|
$stmt = $builder->execute();
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
unset($stmt);
|
|
|
|
foreach ($rs as $row) {
|
|
$mountable_colls[$row['coll_id']] = $row['asciiname'];
|
|
}
|
|
|
|
return $mountable_colls;
|
|
}
|
|
|
|
public function get_activable_colls()
|
|
{
|
|
/** @var Connection $conn */
|
|
$conn = $this->get_appbox()->get_connection();
|
|
$base_ids = [];
|
|
|
|
$sql = 'SELECT base_id FROM bas WHERE sbas_id = :sbas_id AND active = "0"';
|
|
$stmt = $conn->prepare($sql);
|
|
$stmt->execute([':sbas_id' => $this->id]);
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
foreach ($rs as $row) {
|
|
$base_ids[] = (int) $row['base_id'];
|
|
}
|
|
|
|
return $base_ids;
|
|
}
|
|
|
|
public function saveCterms(DOMDocument $dom_cterms)
|
|
{
|
|
$dom_cterms->documentElement->setAttribute("modification_date", $now = date("YmdHis"));
|
|
|
|
$sql = "UPDATE pref SET value = :xml, updated_on = :date
|
|
WHERE prop='cterms'";
|
|
|
|
$this->cterms = $dom_cterms->saveXML();
|
|
$params = [
|
|
':xml' => $this->cterms
|
|
, ':date' => $now
|
|
];
|
|
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute($params);
|
|
$stmt->closeCursor();
|
|
|
|
$this->databoxRepository->save($this);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function saveThesaurus(DOMDocument $dom_thesaurus)
|
|
{
|
|
$old_thesaurus = $this->get_dom_thesaurus();
|
|
|
|
$dom_thesaurus->documentElement->setAttribute("modification_date", $now = date("YmdHis"));
|
|
$this->thesaurus = $dom_thesaurus->saveXML();
|
|
|
|
$sql = "UPDATE pref SET value = :xml, updated_on = :date WHERE prop='thesaurus'";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute([':xml' => $this->thesaurus, ':date' => $now]);
|
|
$stmt->closeCursor();
|
|
$this->delete_data_from_cache(databox::CACHE_THESAURUS);
|
|
|
|
$this->databoxRepository->save($this);
|
|
|
|
$this->app['dispatcher']->dispatch(
|
|
DataboxEvents::THESAURUS_CHANGED,
|
|
new ThesaurusChangedEvent(
|
|
$this,
|
|
array(
|
|
'dom_before'=>$old_thesaurus,
|
|
)
|
|
)
|
|
);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return DOMDocument
|
|
*/
|
|
public function get_dom_thesaurus()
|
|
{
|
|
$sbas_id = $this->id;
|
|
if (isset(self::$_dom_thesaurus[$sbas_id])) {
|
|
return self::$_dom_thesaurus[$sbas_id];
|
|
}
|
|
|
|
$thesaurus = $this->get_thesaurus();
|
|
|
|
$dom = new DOMDocument();
|
|
|
|
if ($thesaurus && false !== $dom->loadXML($thesaurus)) {
|
|
self::$_dom_thesaurus[$sbas_id] = $dom;
|
|
} else {
|
|
self::$_dom_thesaurus[$sbas_id] = false;
|
|
unset($dom);
|
|
}
|
|
|
|
return self::$_dom_thesaurus[$sbas_id];
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function get_thesaurus()
|
|
{
|
|
try {
|
|
$this->thesaurus = $this->get_data_from_cache(self::CACHE_THESAURUS);
|
|
|
|
return $this->thesaurus;
|
|
} catch (\Exception $e) {
|
|
unset($e);
|
|
}
|
|
|
|
try {
|
|
$sql = 'SELECT value AS thesaurus FROM pref WHERE prop="thesaurus" LIMIT 1;';
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
$this->thesaurus = $row['thesaurus'];
|
|
$this->set_data_to_cache($this->thesaurus, self::CACHE_THESAURUS);
|
|
} catch (\Exception $e) {
|
|
unset($e);
|
|
}
|
|
|
|
return $this->thesaurus;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param User $user
|
|
* @return databox
|
|
*/
|
|
public function registerAdmin(User $user)
|
|
{
|
|
$conn = $this->get_appbox()->get_connection();
|
|
|
|
$this->app->getAclForUser($user)
|
|
->give_access_to_sbas([$this->id])
|
|
->update_rights_to_sbas(
|
|
$this->id,
|
|
[
|
|
\ACL::BAS_MANAGE => true,
|
|
\ACL::BAS_MODIFY_STRUCT => true,
|
|
\ACL::BAS_MODIF_TH => true,
|
|
\ACL::BAS_CHUPUB => true
|
|
]
|
|
);
|
|
|
|
$sql = "SELECT * FROM coll";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
$sql = "INSERT INTO bas (active, server_coll_id, sbas_id) VALUES ('1', :coll_id, :sbas_id)";
|
|
$stmt = $conn->prepare($sql);
|
|
|
|
$base_ids = [];
|
|
foreach ($rs as $row) {
|
|
try {
|
|
$stmt->execute([':coll_id' => $row['coll_id'], ':sbas_id' => $this->id]);
|
|
$base_ids[] = $base_id = $conn->lastInsertId();
|
|
|
|
if ( ! empty($row['logo'])) {
|
|
file_put_contents($this->app['root.path'] . '/config/minilogos/' . $base_id, $row['logo']);
|
|
}
|
|
} catch (\Exception $e) {
|
|
unset($e);
|
|
}
|
|
}
|
|
$stmt->closeCursor();
|
|
|
|
$this->app->getAclForUser($user)->give_access_to_base($base_ids);
|
|
|
|
foreach ($base_ids as $base_id) {
|
|
$this->app->getAclForUser($user)
|
|
->update_rights_to_base(
|
|
$base_id,
|
|
[
|
|
\ACL::CANPUSH => true,
|
|
\ACL::CANCMD => true,
|
|
\ACL::CANPUTINALBUM => true,
|
|
\ACL::CANDWNLDHD => true,
|
|
\ACL::CANDWNLDPREVIEW => true,
|
|
\ACL::CANADMIN => true,
|
|
\ACL::ACTIF => true,
|
|
\ACL::CANREPORT => true,
|
|
\ACL::CANADDRECORD => true,
|
|
\ACL::CANMODIFRECORD => true,
|
|
\ACL::CANDELETERECORD => true,
|
|
\ACL::CHGSTATUS => true,
|
|
\ACL::IMGTOOLS => true,
|
|
\ACL::COLL_MANAGE => true,
|
|
\ACL::COLL_MODIFY_STRUCT => true,
|
|
\ACL::NOWATERMARK => true
|
|
]
|
|
);
|
|
}
|
|
|
|
$this->app->getAclForUser($user)->delete_data_from_cache();
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function clear_logs()
|
|
{
|
|
foreach (['log', 'log_docs', 'log_search', 'log_view', 'log_thumb'] as $table) {
|
|
$this->get_connection()->delete($table, []);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function clearCandidates()
|
|
{
|
|
try {
|
|
$domct = $this->get_dom_cterms();
|
|
|
|
if ($domct !== false) {
|
|
$changed = false;
|
|
$nodesToDel = [];
|
|
// loop on first level : "fields"
|
|
for($n = $domct->documentElement->firstChild; $n; $n = $n->nextSibling) {
|
|
if($n->nodeType == XML_ELEMENT_NODE && !($n->getAttribute('delbranch'))){
|
|
$nodesToDel2 = [];
|
|
// loop on 2nd level : "terms"
|
|
for($n2 = $n->firstChild; $n2; $n2 = $n2->nextSibling) {
|
|
// do not remove "rejected" candidates
|
|
if(substr($n2->getAttribute('id'), 0, 1) != 'R') {
|
|
$nodesToDel2[] = $n2;
|
|
}
|
|
}
|
|
foreach($nodesToDel2 as $n2) {
|
|
$n->removeChild($n2);
|
|
$changed = true;
|
|
}
|
|
// if a field has no more candidates, we can remove it
|
|
if(!($n->firstChild)) {
|
|
$nodesToDel[] = $n;
|
|
}
|
|
}
|
|
}
|
|
foreach($nodesToDel as $n) {
|
|
$n->parentNode->removeChild($n);
|
|
$changed = true;
|
|
}
|
|
if($changed) {
|
|
$this->saveCterms($domct);
|
|
}
|
|
}
|
|
}
|
|
catch (\Exception $e) {
|
|
// no-op
|
|
}
|
|
}
|
|
|
|
public function reindex()
|
|
{
|
|
$this->clearCandidates();
|
|
$this->get_connection()->update('pref', ['updated_on' => '0000-00-00 00:00:00'], ['prop' => 'indexes']);
|
|
|
|
// Set TO_INDEX flag on all records
|
|
$sql = "UPDATE record SET jeton = ((jeton & ~ :token_and) | :token_or)";
|
|
$stmt = $this->connection->prepare($sql);
|
|
$stmt->bindValue(':token_and', PhraseaTokens::INDEXING, PDO::PARAM_INT);
|
|
$stmt->bindValue(':token_or', PhraseaTokens::TO_INDEX, PDO::PARAM_INT);
|
|
$stmt->execute();
|
|
|
|
$this->app['dispatcher']->dispatch(
|
|
DataboxEvents::REINDEX_ASKED,
|
|
new ReindexAskedEvent(
|
|
$this
|
|
)
|
|
);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return DOMXpath
|
|
*/
|
|
public function get_xpath_thesaurus()
|
|
{
|
|
$sbas_id = $this->id;
|
|
if (isset(self::$_xpath_thesaurus[$sbas_id])) {
|
|
return self::$_xpath_thesaurus[$sbas_id];
|
|
}
|
|
|
|
$DOM_thesaurus = $this->get_dom_thesaurus();
|
|
|
|
if ($DOM_thesaurus && ($tmp = new thesaurus_xpath($DOM_thesaurus)) !== false)
|
|
self::$_xpath_thesaurus[$sbas_id] = $tmp;
|
|
else
|
|
self::$_xpath_thesaurus[$sbas_id] = false;
|
|
|
|
return self::$_xpath_thesaurus[$sbas_id];
|
|
}
|
|
|
|
/**
|
|
* @return SimpleXMLElement
|
|
*/
|
|
public function get_sxml_thesaurus()
|
|
{
|
|
$sbas_id = $this->id;
|
|
if (isset(self::$_sxml_thesaurus[$sbas_id])) {
|
|
return self::$_sxml_thesaurus[$sbas_id];
|
|
}
|
|
|
|
$thesaurus = $this->get_thesaurus();
|
|
|
|
if ($thesaurus && false !== $tmp = simplexml_load_string($thesaurus))
|
|
self::$_sxml_thesaurus[$sbas_id] = $tmp;
|
|
else
|
|
self::$_sxml_thesaurus[$sbas_id] = false;
|
|
|
|
return self::$_sxml_thesaurus[$sbas_id];
|
|
}
|
|
|
|
/**
|
|
* @return DOMDocument
|
|
*/
|
|
public function get_dom_cterms()
|
|
{
|
|
if ($this->_dom_cterms) {
|
|
return $this->_dom_cterms;
|
|
}
|
|
|
|
$cterms = $this->get_cterms();
|
|
|
|
$dom = new DOMDocument();
|
|
|
|
$dom->standalone = true;
|
|
$dom->preserveWhiteSpace = false;
|
|
$dom->formatOutput = true;
|
|
|
|
if ($cterms && $dom->loadXML($cterms) !== false)
|
|
$this->_dom_cterms = $dom;
|
|
else
|
|
$this->_dom_cterms = false;
|
|
|
|
return $this->_dom_cterms;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_cterms()
|
|
{
|
|
if ($this->cterms) {
|
|
return $this->cterms;
|
|
}
|
|
|
|
$sql = "SELECT value FROM pref WHERE prop='cterms'";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
if ($row)
|
|
$this->cterms = $row['value'];
|
|
|
|
return $this->cterms;
|
|
}
|
|
|
|
public function update_cgus($locale, $terms, $reset_date)
|
|
{
|
|
$old_tou = $this->get_cgus();
|
|
|
|
$terms = str_replace(["\r\n", "\n", "\r"], ['', '', ''], strip_tags($terms, '<p><strong><a><ul><ol><li><h1><h2><h3><h4><h5><h6>'));
|
|
$sql = 'UPDATE pref SET value = :terms ';
|
|
|
|
if ($reset_date)
|
|
$sql .= ', updated_on=NOW() ';
|
|
|
|
$sql .= ' WHERE prop="ToU" AND locale = :locale';
|
|
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute([':terms' => $terms, ':locale' => $locale]);
|
|
$stmt->closeCursor();
|
|
$this->cgus = null;
|
|
$this->delete_data_from_cache(self::CACHE_CGUS);
|
|
|
|
$this->app['dispatcher']->dispatch(
|
|
DataboxEvents::TOU_CHANGED,
|
|
new TouChangedEvent(
|
|
$this,
|
|
[
|
|
'tou_before'=>$old_tou,
|
|
]
|
|
)
|
|
);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function get_cgus()
|
|
{
|
|
if ($this->cgus) {
|
|
return $this->cgus;
|
|
}
|
|
|
|
$this->load_cgus();
|
|
|
|
return $this->cgus;
|
|
}
|
|
|
|
public function __sleep()
|
|
{
|
|
$this->_sxml_structure = $this->_dom_structure = $this->_xpath_structure = null;
|
|
|
|
$vars = [];
|
|
|
|
foreach ($this as $key => $value) {
|
|
if (in_array($key, ['app', 'meta_struct'])) {
|
|
continue;
|
|
}
|
|
|
|
$vars[] = $key;
|
|
}
|
|
|
|
return $vars;
|
|
}
|
|
|
|
public function hydrate(Application $app)
|
|
{
|
|
$this->app = $app;
|
|
}
|
|
|
|
/**
|
|
* Tells whether the registration is enable or not.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isRegistrationEnabled()
|
|
{
|
|
if (false !== $xml = $this->get_sxml_structure()) {
|
|
foreach ($xml->xpath('/record/caninscript') as $canRegister) {
|
|
if (false !== (Boolean) (string) $canRegister) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* matches a email against the auto-register whitelist
|
|
*
|
|
* @param string $email
|
|
* @return null|string the user-model to apply if the email matches
|
|
*/
|
|
public function getAutoregisterModel($email)
|
|
{
|
|
if(!$this->isRegistrationEnabled()) {
|
|
return null;
|
|
}
|
|
|
|
$ret = User::USER_AUTOREGISTER; // default if there is no whitelist defined at all
|
|
|
|
// try to match against the whitelist
|
|
if( ($xml = $this->get_sxml_structure()) !== false) {
|
|
$wl = $xml->xpath('/record/registration/auto_register/email_whitelist');
|
|
if($wl !== false && count($wl) === 1) {
|
|
$ret = null; // there IS a whitelist, the email must match
|
|
|
|
foreach ($wl[0]->xpath('email') as $element) {
|
|
if (preg_match($element['pattern'], $email) === 1) {
|
|
return (string)$element['user_model'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return an array that can be used to restore databox.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getRawData()
|
|
{
|
|
return [
|
|
'ord' => $this->ord,
|
|
'viewname' => $this->viewname,
|
|
'label_en' => $this->labels['en'],
|
|
'label_fr' => $this->labels['fr'],
|
|
'label_de' => $this->labels['de'],
|
|
'label_nl' => $this->labels['nl'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Return the default subdef path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSubdefStorage(){
|
|
|
|
return p4string::addEndSlash($this->app['conf']->get(['main', 'storage', 'subdefs'])).$this->get_dbname()."/subdefs/";
|
|
}
|
|
|
|
protected function retrieve_structure()
|
|
{
|
|
try {
|
|
$data = $this->get_data_from_cache(self::CACHE_STRUCTURE);
|
|
if (is_array($data)) {
|
|
return $data;
|
|
}
|
|
} catch (\Exception $e) {
|
|
|
|
}
|
|
|
|
$structure = null;
|
|
$sql = "SELECT value FROM pref WHERE prop='structure'";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
if ($row)
|
|
$structure = $row['value'];
|
|
$this->set_data_to_cache($structure, self::CACHE_STRUCTURE);
|
|
|
|
return $structure;
|
|
}
|
|
|
|
protected function load_cgus()
|
|
{
|
|
try {
|
|
$this->cgus = $this->get_data_from_cache(self::CACHE_CGUS);
|
|
|
|
return $this;
|
|
} catch (\Exception $e) {
|
|
|
|
}
|
|
|
|
$sql = 'SELECT value, locale, updated_on FROM pref WHERE prop ="ToU"';
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
$stmt->execute();
|
|
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$stmt->closeCursor();
|
|
|
|
$TOU = [];
|
|
foreach ($rs as $row) {
|
|
$TOU[$row['locale']] = ['updated_on' => $row['updated_on'], 'value' => $row['value']];
|
|
}
|
|
|
|
$missing_locale = [];
|
|
|
|
$avLanguages = $this->app['locales.available'];
|
|
foreach ($avLanguages as $code => $language) {
|
|
if (!isset($TOU[$code])) {
|
|
$missing_locale[] = $code;
|
|
}
|
|
}
|
|
|
|
$TOU = array_intersect_key($TOU, $avLanguages);
|
|
|
|
$date_obj = new DateTime();
|
|
$date = $this->app['date-formatter']->format_mysql($date_obj);
|
|
$sql = "INSERT INTO pref (id, prop, value, locale, updated_on, created_on)
|
|
VALUES (null, 'ToU', '', :locale, :date, NOW())";
|
|
$stmt = $this->get_connection()->prepare($sql);
|
|
foreach ($missing_locale as $v) {
|
|
$stmt->execute([':locale' => $v, ':date' => $date]);
|
|
$TOU[$v] = ['updated_on' => $date, 'value' => ''];
|
|
}
|
|
$stmt->closeCursor();
|
|
$this->cgus = $TOU;
|
|
|
|
$this->set_data_to_cache($TOU, self::CACHE_CGUS);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array $row
|
|
*/
|
|
private function loadFromRow(array $row)
|
|
{
|
|
$this->ord = $row['ord'];
|
|
$this->viewname = $row['viewname'];
|
|
$this->labels['fr'] = $row['label_fr'];
|
|
$this->labels['en'] = $row['label_en'];
|
|
$this->labels['de'] = $row['label_de'];
|
|
$this->labels['nl'] = $row['label_nl'];
|
|
}
|
|
}
|