mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-24 10:23:17 +00:00
Split display status & type property into two separate controllers
This commit is contained in:
@@ -38,11 +38,11 @@ class Property implements ControllerProviderInterface
|
||||
});
|
||||
|
||||
/**
|
||||
* Display records property
|
||||
* Display records status property
|
||||
*
|
||||
* name : display_property
|
||||
* name : display_status_property
|
||||
*
|
||||
* description : Display records property
|
||||
* description : Display records status property
|
||||
*
|
||||
* method : GET
|
||||
*
|
||||
@@ -50,8 +50,24 @@ class Property implements ControllerProviderInterface
|
||||
*
|
||||
* return : HTML Response
|
||||
*/
|
||||
$controllers->get('/', $this->call('displayProperty'))
|
||||
->bind('display_property');
|
||||
$controllers->get('/', $this->call('displayStatusProperty'))
|
||||
->bind('display_status_property');
|
||||
|
||||
/**
|
||||
* Display records status property
|
||||
*
|
||||
* name : display_type_property
|
||||
*
|
||||
* description : Display records status property
|
||||
*
|
||||
* method : GET
|
||||
*
|
||||
* parameters : none
|
||||
*
|
||||
* return : HTML Response
|
||||
*/
|
||||
$controllers->get('/type/', $this->call('displayTypeProperty'))
|
||||
->bind('display_type_property');
|
||||
|
||||
/**
|
||||
* Change records status
|
||||
@@ -89,83 +105,55 @@ class Property implements ControllerProviderInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Display property
|
||||
* Display Status property
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function displayProperty(Application $app, Request $request)
|
||||
public function displayStatusProperty(Application $app, Request $request)
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
$app->abort(400);
|
||||
}
|
||||
|
||||
$records = RecordsRequest::fromRequest($app, $request, false, array('chgstatus', 'canmodifrecord'));
|
||||
$records = RecordsRequest::fromRequest($app, $request, false, array('chgstatus'));
|
||||
$databoxStatus = \databox_status::getDisplayStatus($app);
|
||||
$statusBit = $recordsType = $nRec = $toRemove = array();
|
||||
$statusBit = $nRec = array();
|
||||
|
||||
foreach ($records as $key => $record) {
|
||||
if (!$app['phraseanet.user']->ACL()->has_hd_grant($record) ||
|
||||
!$app['phraseanet.user']->ACL()->has_preview_grant($record)) {
|
||||
try {
|
||||
$stmt = $record->get_databox()->get_connection()->prepare(sprintf('SELECT record_id FROM record WHERE ((status ^ %s) & %s) = 0 AND record_id = :record_id', $app['phraseanet.user']->ACL()->get_mask_xor($record->get_base_id()), $app['phraseanet.user']->ACL()->get_mask_and($record->get_base_id())));
|
||||
$stmt->execute(array(':record_id' => $record->get_record_id()));
|
||||
foreach ($records as $record) {
|
||||
|
||||
if (0 === $stmt->rowCount()) {
|
||||
$toRemove[] = $key;
|
||||
} else {
|
||||
//perform logic
|
||||
$sbasId = $record->get_databox()->get_sbas_id();
|
||||
if ($this->isEligible($app, $record)) {
|
||||
//perform logic
|
||||
$sbasId = $record->get_databox()->get_sbas_id();
|
||||
|
||||
if (!isset($nRec[$sbasId])) {
|
||||
$nRec[$sbasId] = array('stories' => 0, 'records' => 0);
|
||||
}
|
||||
if (!isset($nRec[$sbasId])) {
|
||||
$nRec[$sbasId] = array('stories' => 0, 'records' => 0);
|
||||
}
|
||||
|
||||
$nRec[$sbasId]['records']++;
|
||||
$nRec[$sbasId]['records']++;
|
||||
|
||||
if ($record->is_grouping()) {
|
||||
$nRec[$sbasId]['stories']++;
|
||||
}
|
||||
if ($record->is_grouping()) {
|
||||
$nRec[$sbasId]['stories']++;
|
||||
}
|
||||
|
||||
if (!isset($recordsType[$sbasId])) {
|
||||
$recordsType[$sbasId] = array();
|
||||
}
|
||||
if (!isset($statusBit[$sbasId])) {
|
||||
|
||||
if (!isset($recordsType[$sbasId][$record->get_type()])) {
|
||||
$recordsType[$sbasId][$record->get_type()] = array();
|
||||
}
|
||||
$statusBit[$sbasId] = isset($databoxStatus[$sbasId]) ? $databoxStatus[$sbasId] : array();
|
||||
|
||||
$recordsType[$sbasId][$record->get_type()][] = $record;
|
||||
|
||||
if (!isset($statusBit[$sbasId])) {
|
||||
|
||||
$statusBit[$sbasId] = isset($databoxStatus[$sbasId]) ? $databoxStatus[$sbasId] : array();
|
||||
|
||||
foreach (array_keys($statusBit[$sbasId]) as $bit) {
|
||||
$statusBit[$sbasId][$bit]['nset'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$status = strrev($record->get_status());
|
||||
|
||||
foreach (array_keys($statusBit[$sbasId]) as $bit) {
|
||||
$statusBit[$sbasId][$bit]["nset"] += substr($status, $bit, 1) !== "0" ? 1 : 0;
|
||||
}
|
||||
foreach (array_keys($statusBit[$sbasId]) as $bit) {
|
||||
$statusBit[$sbasId][$bit]['nset'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->closeCursor();
|
||||
unset($stmt);
|
||||
} catch (\Exception $e) {
|
||||
$toRemove[] = $key;
|
||||
$status = strrev($record->get_status());
|
||||
|
||||
foreach (array_keys($statusBit[$sbasId]) as $bit) {
|
||||
$statusBit[$sbasId][$bit]["nset"] += substr($status, $bit, 1) !== "0" ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($toRemove as $key) {
|
||||
$records->remove($key);
|
||||
}
|
||||
|
||||
foreach ($records->databoxes() as $databox) {
|
||||
$sbasId = $databox->get_sbas_id();
|
||||
foreach ($statusBit[$sbasId] as $bit => $values) {
|
||||
@@ -174,10 +162,50 @@ class Property implements ControllerProviderInterface
|
||||
}
|
||||
|
||||
return new Response($app['twig']->render('prod/actions/Property/index.html.twig', array(
|
||||
'records' => $records,
|
||||
'statusBit' => $statusBit,
|
||||
'nRec' => $nRec
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display type property
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function displayTypeProperty(Application $app, Request $request)
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
$app->abort(400);
|
||||
}
|
||||
|
||||
$records = RecordsRequest::fromRequest($app, $request, false, array('canmodifrecord'));
|
||||
|
||||
$recordsType = array();
|
||||
|
||||
foreach ($records as $record) {
|
||||
|
||||
if ($this->isEligible($app, $record)) {
|
||||
//perform logic
|
||||
$sbasId = $record->get_databox()->get_sbas_id();
|
||||
|
||||
if (!isset($recordsType[$sbasId])) {
|
||||
$recordsType[$sbasId] = array();
|
||||
}
|
||||
|
||||
if (!isset($recordsType[$sbasId][$record->get_type()])) {
|
||||
$recordsType[$sbasId][$record->get_type()] = array();
|
||||
}
|
||||
|
||||
$recordsType[$sbasId][$record->get_type()][] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
return new Response($app['twig']->render('prod/actions/Property/type.html.twig', array(
|
||||
'records' => $records,
|
||||
'statusBit' => $statusBit,
|
||||
'recordsType' => $recordsType,
|
||||
'nRec' => $nRec
|
||||
)));
|
||||
}
|
||||
|
||||
@@ -277,6 +305,38 @@ class Property implements ControllerProviderInterface
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Application $app
|
||||
* @param record_adapter $record
|
||||
* @return boolean
|
||||
*/
|
||||
private function isEligible(Application $app, \record_adapter $record)
|
||||
{
|
||||
$eligible = false;
|
||||
|
||||
if (!$app['phraseanet.user']->ACL()->has_hd_grant($record) ||
|
||||
!$app['phraseanet.user']->ACL()->has_preview_grant($record)) {
|
||||
try {
|
||||
$stmt = $record->get_databox()->get_connection()->prepare(sprintf('SELECT record_id FROM record WHERE ((status ^ %s) & %s) = 0 AND record_id = :record_id', $app['phraseanet.user']->ACL()->get_mask_xor($record->get_base_id()), $app['phraseanet.user']->ACL()->get_mask_and($record->get_base_id())));
|
||||
$stmt->execute(array(':record_id' => $record->get_record_id()));
|
||||
|
||||
if ($stmt->rowCount() > 0) {
|
||||
$eligible = true;
|
||||
}
|
||||
|
||||
$stmt->closeCursor();
|
||||
unset($stmt);
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
} else {
|
||||
$eligible = true;
|
||||
}
|
||||
|
||||
return $eligible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix the method to call with the controller class name
|
||||
*
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
{% import 'common/thumbnail.html.twig' as thumbnail %}
|
||||
|
||||
{% set nbReceivedDocuments = records.received().count() %}
|
||||
{% set nbEditableDocuments = records.count() %}
|
||||
|
||||
<div id='tabs-records-property'>
|
||||
|
||||
{# This value is fetched when click on 2nd tab #}
|
||||
<input type="hidden" name='original_selection' value="{{ app.request.query.get('lst') }}">
|
||||
|
||||
<ul>
|
||||
<li><a href="#property-statut">{% trans 'Records Statut' %}</a></li>
|
||||
<li><a href="#property-type">{% trans 'Records type' %}</a></li>
|
||||
{# <span> </span> element is required for the jQuery loading spinner appears && disappears properly #}
|
||||
<li><a href="/prod/records/property/type/">{% trans 'Records type' %} <span> </span></a></li>
|
||||
</ul>
|
||||
|
||||
<div id='property-statut'>
|
||||
@@ -112,75 +116,28 @@
|
||||
{% endfor %}
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-primary submiter">{% trans "Apply changes" %}</button>
|
||||
<button type="button" class="btn">{% trans "Cancel" %}</button>
|
||||
<button type="button" class="btn cancel">{% trans "Cancel" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id='property-type'>
|
||||
{% set typesEnum = [
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_AUDIO'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_VIDEO'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_DOCUMENT'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_FLASH'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_IMAGE')
|
||||
]
|
||||
%}
|
||||
|
||||
<form name="change-records-type" action="/prod/records/property/type/" method="POST">
|
||||
<div class='well-small 'style="text-align:center;">
|
||||
<select name='force_types' style="width:250px">
|
||||
<option value="">{% trans 'Apply to all selected documents' %}</option>
|
||||
{% for option in typesEnum %}
|
||||
<option value="{{ option }}">{{ option }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<input name="lst" type="hidden" value="{{ records.serializedList() }}"/>
|
||||
{% for sbasId,databoxTypes in recordsType %}
|
||||
<h2 style="text-align:center;" clas="header">{{ sbasId|sbas_names(app) }}</h2>
|
||||
{% for currentType, recordsByType in databoxTypes %}
|
||||
<ul class="thumbnails" style="margin:20px auto;">
|
||||
{% for record in recordsByType %}
|
||||
<li class="span2">
|
||||
<div class="thumbnail" style='min-height:205px'>
|
||||
{{ thumbnail.format(record.get_thumbnail(), 160, 120, '', false, false) }}
|
||||
<div class="caption">
|
||||
<h5>{{ record.get_title() }}</h5>
|
||||
<p>
|
||||
<select name="types[{{record.get_serialize_key()}}]" style='width:100%'>
|
||||
{% for option in typesEnum %}
|
||||
<option value="{{ option }}" {{ record.is_grouping() ? "disabled='disabled'": "" }} {{ option == record.get_type() ? "selected='selected'" : '' }}>{{ option }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-primary submiter">{% trans "Apply changes" %}</button>
|
||||
<button type="button" class="btn">{% trans "Cancel" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$("#tabs-records-property").tabs();
|
||||
$("#tabs-records-property").tabs({
|
||||
ajaxOptions: {
|
||||
data : {
|
||||
lst: $("input[name=original_selection]", $(this)).val()
|
||||
}
|
||||
},
|
||||
cache: true //Load template only once
|
||||
});
|
||||
|
||||
var $dialog = p4.Dialog.get(1);
|
||||
var $dialogBox = $dialog.getDomElement();
|
||||
|
||||
var button = $(".submiter", $dialogBox);
|
||||
|
||||
button.bind("click", function(){
|
||||
|
||||
$("button.submiter", $dialogBox).bind("click", function(){
|
||||
var $this = $(this);
|
||||
var form = $(this).closest("form");
|
||||
|
||||
$.ajax({
|
||||
@@ -189,14 +146,14 @@
|
||||
data: form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend:function(){
|
||||
button.attr("disabled", true);
|
||||
$this.attr("disabled", true);
|
||||
//@todo add loader
|
||||
},
|
||||
success: function(data){
|
||||
$dialog.Close(1);
|
||||
$dialog.Close();
|
||||
},
|
||||
complete: function(){
|
||||
button.attr("disabled", false);
|
||||
$this.attr("disabled", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
78
templates/web/prod/actions/Property/type.html.twig
Normal file
78
templates/web/prod/actions/Property/type.html.twig
Normal file
@@ -0,0 +1,78 @@
|
||||
{% import 'common/thumbnail.html.twig' as thumbnail %}
|
||||
|
||||
{% set typesEnum = [
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_AUDIO'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_VIDEO'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_DOCUMENT'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_FLASH'),
|
||||
constant('\\Alchemy\\Phrasea\\Media\\Type\\Type::TYPE_IMAGE')
|
||||
]
|
||||
%}
|
||||
|
||||
<form style='padding:15px;' name="change-records-type" action="/prod/records/property/type/" method="POST">
|
||||
<div class='well-small 'style="text-align:center;">
|
||||
<select name='force_types' style="width:250px">
|
||||
<option value="">{% trans 'Apply to all selected documents' %}</option>
|
||||
{% for option in typesEnum %}
|
||||
<option value="{{ option }}">{{ option }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<input name="lst" type="hidden" value="{{ records.serializedList() }}"/>
|
||||
{% for sbasId,databoxTypes in recordsType %}
|
||||
<h2 style="text-align:center;" clas="header">{{ sbasId|sbas_names(app) }}</h2>
|
||||
{% for currentType, recordsByType in databoxTypes %}
|
||||
<ul class="thumbnails" style="margin:20px auto;">
|
||||
{% for record in recordsByType %}
|
||||
<li class="span2">
|
||||
<div class="thumbnail" style='min-height:205px'>
|
||||
{{ thumbnail.format(record.get_thumbnail(), 160, 120, '', false, false) }}
|
||||
<div class="caption">
|
||||
<h5>{{ record.get_title() }}</h5>
|
||||
<p>
|
||||
<select name="types[{{record.get_serialize_key()}}]" style='width:100%'>
|
||||
{% for option in typesEnum %}
|
||||
<option value="{{ option }}" {{ record.is_grouping() ? "disabled='disabled'": "" }} {{ option == record.get_type() ? "selected='selected'" : '' }}>{{ option }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-primary submiter">{% trans "Apply changes" %}</button>
|
||||
<button type="button" class="btn cancel">{% trans "Cancel" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $dialog = p4.Dialog.get(1);
|
||||
var $dialogBox = $dialog.getDomElement();
|
||||
|
||||
$("button.submiter", $dialogBox).bind("click", function(){
|
||||
var $this = $(this);
|
||||
var form = $(this).closest("form");
|
||||
|
||||
$.ajax({
|
||||
type: form.attr("method"),
|
||||
url: form.attr("action"),
|
||||
data: form.serializeArray(),
|
||||
dataType: 'json',
|
||||
beforeSend:function(){
|
||||
$this.attr("disabled", true);
|
||||
//@todo add loader
|
||||
},
|
||||
success: function(data){
|
||||
$dialog.Close();
|
||||
},
|
||||
complete: function(){
|
||||
$this.attr("disabled", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -10,15 +10,40 @@ class PropertyTest extends \PhraseanetWebTestCaseAuthenticatedAbstract
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @covers Alchemy\Phrasea\Controller\Prod\Record\Property::displayProperty
|
||||
* @covers Alchemy\Phrasea\Controller\Prod\Record\Property::displayStatusProperty
|
||||
*/
|
||||
public function testDisplayProperty()
|
||||
public function testDisplayStatusProperty()
|
||||
{
|
||||
$property = new Property();
|
||||
$request = Request::create('/prod/records/property/', 'GET', array(
|
||||
'lst' => implode(';', array(self::$DI['record_no_access']->get_serialize_key(), self::$DI['record_1']->get_serialize_key(), self::$DI['record_4']->get_serialize_key()))
|
||||
), array(), array(), array('HTTP_X-Requested-With' => 'XMLHttpRequest'));
|
||||
$response = $property->displayProperty(self::$DI['app'], $request);
|
||||
$response = $property->displayStatusProperty(self::$DI['app'], $request);
|
||||
$this->assertTrue($response->isOk());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
* @covers Alchemy\Phrasea\Controller\Prod\Record\Property::displayStatusProperty
|
||||
*/
|
||||
public function testDisplayStatusPropertyNotXMLHTTPRequets()
|
||||
{
|
||||
$property = new Property();
|
||||
$request = Request::create('/prod/records/property/', 'GET');
|
||||
$property->displayStatusProperty(self::$DI['app'], $request);
|
||||
unset($property, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Alchemy\Phrasea\Controller\Prod\Record\Property::displayTypeProperty
|
||||
*/
|
||||
public function testDisplayTypeProperty()
|
||||
{
|
||||
$property = new Property();
|
||||
$request = Request::create('/prod/records/property/', 'GET', array(
|
||||
'lst' => implode(';', array(self::$DI['record_no_access']->get_serialize_key(), self::$DI['record_1']->get_serialize_key(), self::$DI['record_4']->get_serialize_key()))
|
||||
), array(), array(), array('HTTP_X-Requested-With' => 'XMLHttpRequest'));
|
||||
$response = $property->displayTypeProperty(self::$DI['app'], $request);
|
||||
$this->assertTrue($response->isOk());
|
||||
}
|
||||
|
||||
@@ -26,18 +51,18 @@ class PropertyTest extends \PhraseanetWebTestCaseAuthenticatedAbstract
|
||||
* @expectedException \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
* @covers Alchemy\Phrasea\Controller\Prod\Record\Property::displayProperty
|
||||
*/
|
||||
public function testDisplayPropertyNotXMLHTTPRequets()
|
||||
public function testDisplayTypePropertyNotXMLHTTPRequets()
|
||||
{
|
||||
$property = new Property();
|
||||
$request = Request::create('/prod/records/property/', 'GET');
|
||||
$property->displayProperty(self::$DI['app'], $request);
|
||||
$property->displayTypeProperty(self::$DI['app'], $request);
|
||||
unset($property, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Alchemy\Phrasea\Controller\Prod\Record\Property::changeStatus
|
||||
*/
|
||||
public function testChangeSTatus()
|
||||
public function testChangeStatus()
|
||||
{
|
||||
$property = new Property();
|
||||
$request = Request::create('/prod/records/property/status/', 'POST', array(
|
||||
|
||||
Reference in New Issue
Block a user