This is a combination of 33 commits.

- Squashed Pull request #1730
- Squashed Pull request #1741
- Squashed Pull request #1742
- Squash merge branch 4.0
- Squashed Pull request #1744
- Squashed Pull request #1746
- Squashed merge branch 4.0
- Squashed merge branch 4.0
- Squashed merge branch 4.0
- Squashed merge branch 4.0
- Squashed Pull request #1758
- Avoid using imagine/imagine alias as it is causing install issues
- Squashed merge branch 4.0
- Squashed Pull request #1763
- Squashed merge branch 4.0
- Squash of 6 commits
- Squashed merge branch 4.0
- This is a combination of 2 commits.
- Squashed Pull request #1775
- Squashed Pull request #1777
- Squashed Pull request #1779
- Squashed Pull request #1780
- Squashed Pull request #1782
- Adds a Pull request template
- Squased Pull request #1783
- Squash Pull request #1786
- Squashed Pull request #1796
- Squashed merge branch 4.0
- Squash Pull request #1791
- Squashed merge branch 4.0
- Squashed Pull request #1808
- Squashed Pull request #1811
- Squashed Pull request #1809
This commit is contained in:
Benoît Burnichon
2016-04-19 19:21:04 +02:00
parent 01b06c5144
commit 1e18b3e69f
179 changed files with 5652 additions and 3030 deletions

View File

@@ -1,5 +1,5 @@
<?php
/**
/*
* This file is part of Phraseanet
*
* (c) 2005-2016 Alchemy
@@ -20,11 +20,8 @@ use Alchemy\Phrasea\Core\Event\Record\RecordEvent;
use Alchemy\Phrasea\Core\Event\Record\RecordEvents;
use Alchemy\Phrasea\Core\Event\Record\StatusChangedEvent;
use Alchemy\Phrasea\Core\PhraseaTokens;
use Alchemy\Phrasea\Databox\Subdef\MediaSubdefRepository;
use Alchemy\Phrasea\Filesystem\FilesystemService;
use Alchemy\Phrasea\Media\ArrayTechnicalDataSet;
use Alchemy\Phrasea\Media\FloatTechnicalData;
use Alchemy\Phrasea\Media\IntegerTechnicalData;
use Alchemy\Phrasea\Media\StringTechnicalData;
use Alchemy\Phrasea\Media\TechnicalData;
use Alchemy\Phrasea\Media\TechnicalDataSet;
use Alchemy\Phrasea\Metadata\Tag\TfBasename;
@@ -42,7 +39,6 @@ use MediaVorus\MediaVorus;
use Ramsey\Uuid\Uuid;
use Symfony\Component\HttpFoundation\File\File as SymfoFile;
class record_adapter implements RecordInterface, cache_cacheableInterface
{
const CACHE_ORIGINAL_NAME = 'originalname';
@@ -52,7 +48,6 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
const CACHE_SHA256 = 'sha256';
const CACHE_SUBDEFS = 'subdefs';
const CACHE_GROUPING = 'grouping';
const CACHE_STATUS = 'status';
/**
* @param Application $app
@@ -82,6 +77,10 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
private $collection_id;
private $mime;
private $number;
/**
* @var string
*/
private $status;
private $subdefs;
private $type;
@@ -92,7 +91,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
private $created;
/** @var string */
private $original_name;
/** @var TechnicalDataSet */
/** @var TechnicalDataSet|null */
private $technical_data;
/** @var string */
private $uuid;
@@ -110,7 +109,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
{
$this->app = $app;
$this->reference = RecordReference::createFromDataboxIdAndRecordId($sbas_id, $record_id);
$this->number = (int) $number;
$this->number = (int)$number;
if ($load) {
$this->load();
@@ -141,6 +140,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
$this->created = $record->getCreated();
$this->base_id = $record->getBaseId();
$this->collection_id = $record->getCollectionId();
$this->status = $record->getStatus();
}
/**
@@ -201,7 +201,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/
public function setNumber($number)
{
$this->number = (int) $number;
$this->number = (int)$number;
return $this;
}
@@ -370,8 +370,19 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
* Return record collection
*
* @return \collection
* @deprecated use {@link self::getCollection} instead.
*/
public function get_collection()
{
return $this->getCollection();
}
/**
* Return collection to which the record belongs to.
*
* @return \collection
*/
public function getCollection()
{
return \collection::getByCollectionId($this->app, $this->getDatabox(), $this->collection_id);
}
@@ -460,7 +471,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/
public function move_to_collection(collection $collection, appbox $appbox)
{
if ($this->get_collection()->get_base_id() === $collection->get_base_id()) {
if ($this->getCollection()->get_base_id() === $collection->get_base_id()) {
return $this;
}
@@ -517,54 +528,9 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this->sha256;
}
/**
* @return string
*/
public function get_status()
{
if (!$this->status) {
$this->status = $this->retrieve_status();
}
return $this->status;
}
/**
* @return string
* @throws Exception
* @throws \Doctrine\DBAL\DBALException
*/
protected function retrieve_status()
{
try {
$data = $this->get_data_from_cache(self::CACHE_STATUS);
} catch (Exception $e) {
$data = false;
}
if (false !== $data) {
return $data;
}
$status = $this->getDataboxConnection()->fetchColumn(
'SELECT BIN(status) as status FROM record WHERE record_id = :record_id',
[':record_id' => $this->getRecordId()]
);
if (false === $status) {
throw new Exception('status not found');
}
$status = str_pad($status, 32, '0', STR_PAD_LEFT);
$this->set_data_to_cache($status, self::CACHE_STATUS);
return $status;
}
public function has_subdef($name)
{
return in_array($name, $this->get_available_subdefs());
return in_array($name, $this->get_available_subdefs(), false);
}
/**
@@ -579,17 +545,13 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this->subdefs[$name];
}
if (!in_array($name, $this->get_available_subdefs())) {
if (!in_array($name, $this->get_available_subdefs(), false)) {
throw new Exception_Media_SubdefNotFound(sprintf("subdef `%s` not found", $name));
}
if (!$this->subdefs) {
$this->subdefs = [];
}
$subdefs = $this->getMediaSubdefRepository()->findOneByRecordIdAndName($this->getRecordId(), $name);
$substitute = ($name !== 'document');
return $this->subdefs[$name] = new media_subdef($this->app, $this, $name, $substitute);
return $subdefs ?: new media_subdef($this->app, $this, $name, ($name !== 'document'));
}
/**
@@ -607,15 +569,15 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
if (isset($availableSubdefs['document'])) {
$mime_ok = !$mimes || in_array($availableSubdefs['document']->get_mime(), (array) $mimes);
$devices_ok = !$devices || array_intersect($availableSubdefs['document']->getDevices(), (array) $devices);
$mime_ok = !$mimes || in_array($availableSubdefs['document']->get_mime(), (array)$mimes, false);
$devices_ok = !$devices || array_intersect($availableSubdefs['document']->getDevices(), (array)$devices);
if ($mime_ok && $devices_ok) {
$subdefs['document'] = $availableSubdefs['document'];
}
}
$searchDevices = array_merge((array) $devices, (array) databox_subdef::DEVICE_ALL);
$searchDevices = array_merge((array)$devices, (array)databox_subdef::DEVICE_ALL);
$type = $this->isStory() ? 'image' : $this->getType();
@@ -641,7 +603,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
continue;
}
if ($mimes && !in_array($subdef->get_mime(), (array) $mimes)) {
if ($mimes && !in_array($subdef->get_mime(), (array)$mimes)) {
continue;
}
@@ -656,13 +618,20 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/
public function get_subdefs()
{
if (!$this->subdefs) {
$this->subdefs = [];
if (null !== $this->subdefs) {
return $this->subdefs;
}
$subdefs = $this->get_available_subdefs();
foreach ($subdefs as $name) {
$this->get_subdef($name);
$this->subdefs = [];
foreach ($this->getMediaSubdefRepository()->findByRecordIdsAndNames([$this->getRecordId()]) as $subdef) {
$this->subdefs[$subdef->get_name()] = $subdef;
}
foreach (['preview', 'thumbnail'] as $name) {
if (!isset($this->subdefs[$name])) {
$this->subdefs[$name] = new media_subdef($this->app, $this, $name, true, []);
}
}
return $this->subdefs;
@@ -673,6 +642,10 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/
protected function get_available_subdefs()
{
if (null !== $this->subdefs) {
return array_keys($this->subdefs);
}
try {
$data = $this->get_data_from_cache(self::CACHE_SUBDEFS);
} catch (\Exception $e) {
@@ -683,18 +656,8 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $data;
}
$rs = $this->getDataboxConnection()->fetchAll(
'SELECT name FROM subdef WHERE record_id = :record_id',
['record_id' => $this->getRecordId()]
);
$subdefs = array_keys($this->get_subdefs());
$subdefs = ['preview', 'thumbnail'];
foreach ($rs as $row) {
$subdefs[] = $row['name'];
}
$subdefs = array_unique($subdefs);
$this->set_data_to_cache($subdefs, self::CACHE_SUBDEFS);
return $subdefs;
@@ -716,13 +679,10 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/
public function get_technical_infos($data = '')
{
if (!$this->technical_data && !$this->mapTechnicalDataFromCache()) {
$this->technical_data = [];
$rs = $this->fetchTechnicalDataFromDb();
if (null === $this->technical_data) {
$sets = $this->app['service.technical_data']->fetchRecordsTechnicalData([$this]);
$this->mapTechnicalDataFromDb($rs);
$this->set_data_to_cache($this->technical_data, self::CACHE_TECHNICAL_DATA);
$this->setTechnicalDataSet(reset($sets));
}
if ($data) {
@@ -736,12 +696,21 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this->technical_data;
}
/**
* @param TechnicalDataSet $dataSet
* @internal
*/
public function setTechnicalDataSet(TechnicalDataSet $dataSet)
{
$this->technical_data = $dataSet;
}
/**
* @return caption_record
*/
public function get_caption()
{
return new caption_record($this->app, $this, $this->getDatabox());
return new caption_record($this->app, $this);
}
public function getCaption(array $fields = null)
@@ -758,7 +727,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
$collection = [];
foreach ($fields as $field) {
$values = array_map(function(caption_Field_Value $fieldValue) {
$values = array_map(function (caption_Field_Value $fieldValue) {
return $fieldValue->getValue();
}, $field->get_values());
@@ -857,7 +826,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
}
if (count($fields_to_retrieve) > 0) {
$retrieved_fields = $this->get_caption()->get_highlight_fields($highlight, $fields_to_retrieve, $searchEngine);
$retrieved_fields = $this->get_caption()->get_highlight_fields($highlight, $fields_to_retrieve);
$titles = [];
foreach ($retrieved_fields as $value) {
foreach ($value['values'] as $v) {
@@ -904,6 +873,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
/**
* @return string
* @deprecated use {@link self::getId} instead.
*/
public function get_serialize_key()
{
@@ -1066,16 +1036,16 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
}
$record = $this;
$wanted_subdefs = array_map(function(databox_subdef $subDef) {
$wanted_subdefs = array_map(function (databox_subdef $subDef) {
return $subDef->get_name();
}, array_filter($subDefDefinitions, function(databox_subdef $subDef) use ($record) {
}, array_filter(iterator_to_array($subDefDefinitions), function (databox_subdef $subDef) use ($record) {
return !$record->has_subdef($subDef->get_name());
}));
$missing_subdefs = array_map(function(media_subdef $subDef) {
$missing_subdefs = array_map(function (media_subdef $subDef) {
return $subDef->get_name();
}, array_filter($this->get_subdefs(), function(media_subdef $subdef) {
}, array_filter($this->get_subdefs(), function (media_subdef $subdef) {
return !$subdef->is_physically_present();
}));
@@ -1096,26 +1066,6 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this;
}
/**
* @param string $status
* @return record_adapter
*/
public function set_binary_status($status)
{
$connection = $this->getDataboxConnection();
$connection->executeUpdate(
'UPDATE record SET moddate = NOW(), status = :status WHERE record_id= :record_id',
['status' => bindec($status), 'record_id' => $this->getRecordId()]
);
$this->delete_data_from_cache(self::CACHE_STATUS);
$this->dispatch(RecordEvents::STATUS_CHANGED, new StatusChangedEvent($this));
return $this;
}
private function dispatch($eventName, RecordEvent $event)
{
$this->app['dispatcher']->dispatch($eventName, $event);
@@ -1255,12 +1205,12 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
}
$connection = $this->getDataboxConnection();
$sql = 'DELETE FROM technical_datas WHERE record_id = :record_id';
$stmt = $connection->prepare($sql);
$stmt->execute([':record_id' => $this->getRecordId()]);
$stmt->closeCursor();
$connection->executeUpdate('DELETE FROM technical_datas WHERE record_id = :record_id', [
':record_id' => $this->getRecordId(),
]);
$sqlValues = [];
foreach ($document->readTechnicalDatas($mediavorus) as $name => $value) {
if (is_null($value)) {
continue;
@@ -1271,21 +1221,15 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
$value = 0;
}
}
$sqlValues[] = join(',', array(
'null',
$connection->quote($this->getRecordId()),
$connection->quote($name),
$connection->quote($value),
));
$sqlValues[] = [$this->getRecordId(), $name, $value];
}
$sql = "INSERT INTO technical_datas (id, record_id, name, value)"
. " VALUES (" . join('),(', $sqlValues) . ")";
;
$stmt = $connection->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
if ($sqlValues) {
$connection->transactional(function (Connection $connection) use ($sqlValues) {
$statement = $connection->prepare('INSERT INTO technical_datas (record_id, name, value) VALUES (?, ?, ?)');
array_walk($sqlValues, [$statement, 'execute']);
});
}
$this->delete_data_from_cache(self::CACHE_TECHNICAL_DATA);
@@ -1357,8 +1301,9 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
$ftodel = [];
foreach ($this->get_subdefs() as $subdef) {
if (!$subdef->is_physically_present())
if (!$subdef->is_physically_present()) {
continue;
}
if ($subdef->get_name() === 'thumbnail') {
$this->app['phraseanet.thumb-symlinker']->unlink($subdef->getRealPath());
@@ -1366,11 +1311,13 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
$ftodel[] = $subdef->getRealPath();
$watermark = $subdef->getWatermarkRealPath();
if (file_exists($watermark))
if (file_exists($watermark)) {
$ftodel[] = $watermark;
}
$stamp = $subdef->getStampRealPath();
if (file_exists($stamp))
if (file_exists($stamp)) {
$ftodel[] = $stamp;
}
}
$origcoll = $this->collection_id;
@@ -1500,16 +1447,13 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
public function delete_data_from_cache($option = null)
{
switch ($option) {
case self::CACHE_STATUS:
$this->status = null;
break;
switch ($option)
{
case self::CACHE_SUBDEFS:
$this->subdefs = null;
break;
default:
break;
}
$databox = $this->getDatabox();
$databox->delete_data_from_cache($this->get_cache_key($option));
@@ -1540,7 +1484,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
/**
* @todo de meme avec stories
* @return Array
* @return \Alchemy\Phrasea\Model\Entities\Basket[]
*/
public function get_container_baskets(EntityManager $em, User $user)
{
@@ -1560,8 +1504,8 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
*/
public static function get_records_by_originalname(databox $databox, $original_name, $caseSensitive = false, $offset_start = 0, $how_many = 10)
{
$offset_start = (int) ($offset_start < 0 ? 0 : $offset_start);
$how_many = (int) (($how_many > 20 || $how_many < 1) ? 10 : $how_many);
$offset_start = (int)($offset_start < 0 ? 0 : $offset_start);
$how_many = (int)(($how_many > 20 || $how_many < 1) ? 10 : $how_many);
$sql = sprintf(
'SELECT record_id FROM record WHERE originalname = :original_name COLLATE %s LIMIT %d, %d',
@@ -1694,7 +1638,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
public function hasChild(\record_adapter $record)
{
return $this->get_children()->offsetExists($record->get_serialize_key());
return $this->getChildren()->offsetExists($record->getId());
}
public function appendChild(\record_adapter $record)
@@ -1786,17 +1730,36 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this->reference->getId();
}
/**
* @param string $status
* @return void
*/
public function setStatus($status)
{
$this->set_binary_status($status);
$this->getDataboxConnection()->executeUpdate(
'UPDATE record SET moddate = NOW(), status = :status WHERE record_id=:record_id',
['status' => bindec($status), 'record_id' => $this->getRecordId()]
);
$this->delete_data_from_cache(self::CACHE_STATUS);
$this->status = str_pad($status, 32, '0', STR_PAD_LEFT);
// modification date is now unknown, delete from cache to reload on another record
$this->delete_data_from_cache();
$this->dispatch(RecordEvents::STATUS_CHANGED, new StatusChangedEvent($this));
}
/**
* @return string
*/
public function getStatus()
{
return $this->status;
}
/** {@inheritdoc} */
public function getStatusBitField()
{
return bindec($this->get_status());
return bindec($this->getStatus());
}
/** {@inheritdoc} */
@@ -1823,6 +1786,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
'created' => $this->created->format(DATE_ISO8601),
'base_id' => $this->base_id,
'collection_id' => $this->collection_id,
'status' => $this->status,
];
$this->set_data_to_cache($data);
@@ -1848,64 +1812,13 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
$this->original_name = $row['originalName'];
$this->sha256 = $row['sha256'];
$this->mime = $row['mime'];
}
/**
* @return bool
*/
private function mapTechnicalDataFromCache()
{
try {
$technical_data = $this->get_data_from_cache(self::CACHE_TECHNICAL_DATA);
} catch (Exception $e) {
$technical_data = false;
}
if (false === $technical_data) {
return false;
}
$this->technical_data = $technical_data;
return true;
}
/**
* @return false|array
*/
private function fetchTechnicalDataFromDb()
{
$sql = 'SELECT name, value FROM technical_datas WHERE record_id = :record_id';
return $this->getDataboxConnection()
->fetchAll($sql, ['record_id' => $this->getRecordId()]);
}
/**
* @param array $rows
*/
private function mapTechnicalDataFromDb(array $rows)
{
$this->technical_data = new ArrayTechnicalDataSet();
foreach ($rows as $row) {
switch (true) {
case ctype_digit($row['value']):
$this->technical_data[] = new IntegerTechnicalData($row['name'], $row['value']);
break;
case preg_match('/[0-9]?\.[0-9]+/', $row['value']):
$this->technical_data[] = new FloatTechnicalData($row['name'], $row['value']);
break;
default:
$this->technical_data[] = new StringTechnicalData($row['name'], $row['value']);
}
}
$this->status = str_pad($row['status'], 32, '0', STR_PAD_LEFT);
}
/**
* @return Connection
*/
private function getDataboxConnection()
protected function getDataboxConnection()
{
if (null === $this->connection) {
$this->connection = $this->getDatabox()->get_connection();
@@ -1913,4 +1826,12 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
return $this->connection;
}
/**
* @return MediaSubdefRepository
*/
private function getMediaSubdefRepository()
{
return $this->app['provider.repo.media_subdef']->getRepositoryForDatabox($this->getDataboxId());
}
}