mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-12 12:33:26 +00:00
PHRAS-374 Add command to rebuild subdefs
This commit is contained in:
@@ -16,6 +16,7 @@ namespace KonsoleKommander;
|
|||||||
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
|
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
|
||||||
* @link www.phraseanet.com
|
* @link www.phraseanet.com
|
||||||
*/
|
*/
|
||||||
|
use Alchemy\Phrasea\Command\BuildSubdefs;
|
||||||
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
|
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
|
||||||
use Alchemy\Phrasea\Command\Setup\H264ConfigurationDumper;
|
use Alchemy\Phrasea\Command\Setup\H264ConfigurationDumper;
|
||||||
use Alchemy\Phrasea\Command\Setup\H264MappingGenerator;
|
use Alchemy\Phrasea\Command\Setup\H264MappingGenerator;
|
||||||
@@ -97,6 +98,7 @@ $cli->command(new CreateCollection('collection:create'));
|
|||||||
$cli->command(new RecordAdd('records:add'));
|
$cli->command(new RecordAdd('records:add'));
|
||||||
$cli->command(new RescanTechnicalDatas('records:rescan-technical-datas'));
|
$cli->command(new RescanTechnicalDatas('records:rescan-technical-datas'));
|
||||||
$cli->command(new BuildMissingSubdefs('records:build-missing-subdefs'));
|
$cli->command(new BuildMissingSubdefs('records:build-missing-subdefs'));
|
||||||
|
$cli->command(new BuildSubdefs('records:build-subdefs'));
|
||||||
|
|
||||||
$cli->command(new AddPlugin());
|
$cli->command(new AddPlugin());
|
||||||
$cli->command(new ListPlugin());
|
$cli->command(new ListPlugin());
|
||||||
|
@@ -44,9 +44,6 @@ class BuildMissingSubdefs extends Command
|
|||||||
$n = 0;
|
$n = 0;
|
||||||
|
|
||||||
foreach ($this->container['phraseanet.appbox']->get_databoxes() as $databox) {
|
foreach ($this->container['phraseanet.appbox']->get_databoxes() as $databox) {
|
||||||
|
|
||||||
$subdefStructure = $databox->get_subdef_structure();
|
|
||||||
|
|
||||||
$sql = 'SELECT record_id FROM record WHERE parent_record_id = 0';
|
$sql = 'SELECT record_id FROM record WHERE parent_record_id = 0';
|
||||||
$stmt = $databox->get_connection()->prepare($sql);
|
$stmt = $databox->get_connection()->prepare($sql);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
@@ -56,38 +53,14 @@ class BuildMissingSubdefs extends Command
|
|||||||
foreach ($rs as $row) {
|
foreach ($rs as $row) {
|
||||||
$record = $databox->get_record($row['record_id']);
|
$record = $databox->get_record($row['record_id']);
|
||||||
|
|
||||||
try {
|
$wanted_subdefs = $record->get_missing_subdefs();
|
||||||
$record->get_hd_file();
|
|
||||||
} catch (FileNotFoundException $e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$group = $subdefStructure->getSubdefGroup($record->get_type());
|
if (count($wanted_subdefs) > 0) {
|
||||||
|
$record->generate_subdefs($databox, $this->container, $wanted_subdefs);
|
||||||
|
|
||||||
if ($group) {
|
foreach ($wanted_subdefs as $subdef) {
|
||||||
foreach ($group as $subdef) {
|
$this->container['monolog']->addInfo("generate " .$subdef . " for record " . $record->get_record_id());
|
||||||
|
$n ++;
|
||||||
$todo = false;
|
|
||||||
|
|
||||||
if ( ! $record->has_subdef($subdef->get_name())) {
|
|
||||||
$todo = true;
|
|
||||||
}
|
|
||||||
if (in_array($subdef->get_name(), array('preview', 'thumbnail', 'thumbnailgif'))) {
|
|
||||||
try {
|
|
||||||
$sub = $record->get_subdef($subdef->get_name());
|
|
||||||
if ( ! $sub->is_physically_present()) {
|
|
||||||
$todo = true;
|
|
||||||
}
|
|
||||||
} catch (\Exception_Media_SubdefNotFound $e) {
|
|
||||||
$todo = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($todo) {
|
|
||||||
$record->generate_subdefs($databox, $this->container, array($subdef->get_name()));
|
|
||||||
$this->container['monolog']->addInfo("generate " . $subdef->get_name() . " for record " . $record->get_record_id());
|
|
||||||
$n ++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
171
lib/Alchemy/Phrasea/Command/BuildSubdefs.php
Normal file
171
lib/Alchemy/Phrasea/Command/BuildSubdefs.php
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2014 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Command;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\DBAL\SQLParserUtils;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class BuildSubdefs extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct($name = null)
|
||||||
|
{
|
||||||
|
parent::__construct($name);
|
||||||
|
|
||||||
|
$this->setDescription('Build subviews for given subview names and record types');
|
||||||
|
$this->addArgument('databox', InputArgument::REQUIRED, 'The databox id');
|
||||||
|
$this->addArgument('type', InputArgument::REQUIRED, 'Types of the document to rebuild');
|
||||||
|
$this->addArgument('subdefs', InputArgument::REQUIRED, 'Names of sub-definition to re-build');
|
||||||
|
$this->addOption('max_record', 'max', InputOption::VALUE_OPTIONAL, 'Max record id');
|
||||||
|
$this->addOption('min_record', 'min', InputOption::VALUE_OPTIONAL, 'Min record id');
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$availableTypes = array('document', 'audio', 'video', 'image', 'flash', 'map');
|
||||||
|
|
||||||
|
$typesOption = $input->getArgument('type');
|
||||||
|
|
||||||
|
$recordsType = explode(',', $typesOption);
|
||||||
|
$recordsType = array_filter($recordsType, function($type) use($availableTypes) {
|
||||||
|
return in_array($type, $availableTypes);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count($recordsType) === 0) {
|
||||||
|
$output->write(sprintf('Invalid records type provided %s', implode(', ', $availableTypes)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subdefsOption = $input->getArgument('subdefs');
|
||||||
|
$subdefsName = explode(',', $subdefsOption);
|
||||||
|
|
||||||
|
if (count($subdefsOption) === 0) {
|
||||||
|
$output->write('No subdef options provided');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sqlCount = "
|
||||||
|
SELECT COUNT(DISTINCT(r.record_id)) AS nb_records
|
||||||
|
FROM record r
|
||||||
|
INNER JOIN subdef s
|
||||||
|
ON (r.record_id = s.record_id)
|
||||||
|
WHERE s.name IN (?)
|
||||||
|
AND r.type IN (?)
|
||||||
|
";
|
||||||
|
|
||||||
|
$types = array(Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY);
|
||||||
|
$params = array($subdefsName, $recordsType);
|
||||||
|
|
||||||
|
if (null !== $min = $input->getOption('min_record')) {
|
||||||
|
$sqlCount .= " AND (r.record_id >= ?)";
|
||||||
|
|
||||||
|
$params[] = (int) $min;
|
||||||
|
$types[] = \PDO::PARAM_INT;
|
||||||
|
}
|
||||||
|
if (null !== $max = $input->getOption('max_record')) {
|
||||||
|
$sqlCount .= " AND (r.record_id <= ?)";
|
||||||
|
|
||||||
|
$params[] = (int) $max;
|
||||||
|
$types[] = \PDO::PARAM_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sqlCount, $stmtParams) = SQLParserUtils::expandListParameters($sqlCount, $params, $types);
|
||||||
|
|
||||||
|
$totalRecords = 0;
|
||||||
|
foreach ($this->container['phraseanet.appbox']->get_databoxes() as $databox) {
|
||||||
|
$connection = $databox->get_connection();
|
||||||
|
$stmt = $connection->prepare($sqlCount);
|
||||||
|
$stmt->execute($stmtParams);
|
||||||
|
$row = $stmt->fetch();
|
||||||
|
$totalRecords += $row['nb_records'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($totalRecords === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$progress = $this->getHelperSet()->get('progress');
|
||||||
|
|
||||||
|
$progress->start($output, $totalRecords);
|
||||||
|
|
||||||
|
$progress->display();
|
||||||
|
|
||||||
|
$databox = $this->container['phraseanet.appbox']->get_databox($input->getArgument('databox'));
|
||||||
|
|
||||||
|
$sql = "
|
||||||
|
SELECT DISTINCT(r.record_id)
|
||||||
|
FROM record r
|
||||||
|
INNER JOIN subdef s
|
||||||
|
ON (r.record_id = s.record_id)
|
||||||
|
WHERE s.name IN (?)
|
||||||
|
AND r.type IN (?)
|
||||||
|
";
|
||||||
|
|
||||||
|
$types = array(Connection::PARAM_STR_ARRAY, Connection::PARAM_STR_ARRAY);
|
||||||
|
$params = array($subdefsName, $recordsType);
|
||||||
|
|
||||||
|
if ($min) {
|
||||||
|
$sql .= " AND (r.record_id >= ?)";
|
||||||
|
|
||||||
|
$params[] = (int) $min;
|
||||||
|
$types[] = \PDO::PARAM_INT;
|
||||||
|
}
|
||||||
|
if ($max) {
|
||||||
|
$sql .= " AND (r.record_id <= ?)";
|
||||||
|
|
||||||
|
$params[] = (int) $max;
|
||||||
|
$types[] = \PDO::PARAM_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($sql, $stmtParams) = SQLParserUtils::expandListParameters($sql, $params, $types);
|
||||||
|
|
||||||
|
$connection = $databox->get_connection();
|
||||||
|
$stmt = $connection->prepare($sql);
|
||||||
|
$stmt->execute($stmtParams);
|
||||||
|
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$output->write(sprintf(' (#%s)', $row['record_id']));
|
||||||
|
|
||||||
|
$record = new \record_adapter($this->container, $databox->get_sbas_id(), $row['record_id']);
|
||||||
|
|
||||||
|
$subdefs = array_filter($record->get_subdefs(), function($subdef) use ($subdefsName) {
|
||||||
|
return in_array($subdef->get_name(), $subdefsName);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($subdefs as $subdef) {
|
||||||
|
$subdef->remove_file();
|
||||||
|
}
|
||||||
|
|
||||||
|
$record->generate_subdefs($databox, $this->container, $subdefsName);
|
||||||
|
|
||||||
|
$stmt->closeCursor();
|
||||||
|
|
||||||
|
$progress->advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($rows, $record, $stmt, $connection);
|
||||||
|
|
||||||
|
$progress->finish();
|
||||||
|
}
|
||||||
|
}
|
@@ -90,10 +90,11 @@ class Tools implements ControllerProviderInterface
|
|||||||
$controllers->post('/image/', function (Application $app, Request $request) {
|
$controllers->post('/image/', function (Application $app, Request $request) {
|
||||||
$return = array('success' => true);
|
$return = array('success' => true);
|
||||||
|
|
||||||
|
$force = $request->request->get('force_substitution') == '1';
|
||||||
|
|
||||||
$selection = RecordsRequest::fromRequest($app, $request, false, array('canmodifrecord'));
|
$selection = RecordsRequest::fromRequest($app, $request, false, array('canmodifrecord'));
|
||||||
|
|
||||||
foreach ($selection as $record) {
|
foreach ($selection as $record) {
|
||||||
|
|
||||||
$substituted = false;
|
$substituted = false;
|
||||||
foreach ($record->get_subdefs() as $subdef) {
|
foreach ($record->get_subdefs() as $subdef) {
|
||||||
if ($subdef->is_substituted()) {
|
if ($subdef->is_substituted()) {
|
||||||
@@ -102,11 +103,12 @@ class Tools implements ControllerProviderInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$substituted || $request->request->get('ForceThumbSubstit') == '1') {
|
if (!$substituted || $force) {
|
||||||
$record->rebuild_subdefs();
|
$record->rebuild_subdefs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $app->json($return);
|
return $app->json($return);
|
||||||
})->bind('prod_tools_image');
|
})->bind('prod_tools_image');
|
||||||
|
|
||||||
|
@@ -1202,7 +1202,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface
|
|||||||
*
|
*
|
||||||
* @return record_adapter
|
* @return record_adapter
|
||||||
*/
|
*/
|
||||||
public function rebuild_subdefs()
|
public function rebuild_subdefs()
|
||||||
{
|
{
|
||||||
$connbas = connection::getPDOConnection($this->app, $this->get_sbas_id());
|
$connbas = connection::getPDOConnection($this->app, $this->get_sbas_id());
|
||||||
$sql = 'UPDATE record SET jeton=(jeton | ' . JETON_MAKE_SUBDEF . ') WHERE record_id = :record_id';
|
$sql = 'UPDATE record SET jeton=(jeton | ' . JETON_MAKE_SUBDEF . ') WHERE record_id = :record_id';
|
||||||
@@ -1213,6 +1213,38 @@ class record_adapter implements record_Interface, cache_cacheableInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get_missing_subdefs()
|
||||||
|
{
|
||||||
|
$databox = $this->get_databox();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->get_hd_file();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$subDefDefinitions = $databox->get_subdef_structure()->getSubdefGroup($this->get_type());
|
||||||
|
if (!$subDefDefinitions) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$record = $this;
|
||||||
|
$wanted_subdefs = array_map(function($subDef) {
|
||||||
|
return $subDef->get_name();
|
||||||
|
}, array_filter($subDefDefinitions, function($subDef) use ($record) {
|
||||||
|
return !$record->has_subdef($subDef->get_name());
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
$missing_subdefs = array_map(function($subDef) {
|
||||||
|
return $subDef->get_name();
|
||||||
|
}, array_filter($this->get_subdefs(), function($subdef) {
|
||||||
|
return !$subdef->is_physically_present();
|
||||||
|
}));
|
||||||
|
|
||||||
|
return array_values(array_merge($wanted_subdefs, $missing_subdefs));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return record_adapter
|
* @return record_adapter
|
||||||
|
@@ -70,25 +70,20 @@
|
|||||||
<legend style='color:#EEE'> <b>{% trans "Reconstruire les sous definitions" %}</b> </legend>
|
<legend style='color:#EEE'> <b>{% trans "Reconstruire les sous definitions" %}</b> </legend>
|
||||||
{% if nbThumbSubstitute > 0 %}
|
{% if nbThumbSubstitute > 0 %}
|
||||||
<div style="color:#A00;">
|
<div style="color:#A00;">
|
||||||
{% trans "Attention, certain documents ont des sous-definitions substituees"%}
|
{% trans "Attention, certain documents ont des sous-definitions substituees" %}
|
||||||
</div>
|
</div>
|
||||||
<label for="FTS" class="checkbox">
|
<label for="FTS" class="checkbox">
|
||||||
<input type="checkbox" name="ForceThumbSubstit" value="1" id="FTS" />
|
<input type="checkbox" name="force_substitution" value="1" id="FTS" />
|
||||||
{% trans "Forcer la reconstruction sur les enregistrements ayant des thumbnails substituees" %}
|
{% trans "Forcer la reconstruction sur les enregistrements ayant des thumbnails substituees" %}
|
||||||
</label>
|
</label>
|
||||||
<br/>
|
<br/>
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="hidden" name="ForceThumbSubstit" value="1">
|
<input type="hidden" name="force_substitution" value="1">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
<select name="rebuild">
|
<p>
|
||||||
<option selected="selected" value="none">
|
{{ 'Are you sure you want to rebuild the sub-definitions of selected records?' }}
|
||||||
{% trans "recreer aucune sous-definitions" %}
|
</p>
|
||||||
</option>
|
|
||||||
<option value="all">
|
|
||||||
{% trans "recreer toutes les sous-definitions" %}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="ACT" value="SEND" />
|
<input type="hidden" name="ACT" value="SEND" />
|
||||||
<input type="hidden" name="lst" value="{{records.serializedList()}}" />
|
<input type="hidden" name="lst" value="{{records.serializedList()}}" />
|
||||||
|
Reference in New Issue
Block a user