From 974f1b8a023f84f4aee3816304be93ab780a70d0 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Fri, 17 Nov 2017 11:32:37 +0400 Subject: [PATCH 01/25] Porting PHRAS-1542 to 4.1 --- templates/web/prod/index.html.twig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig index 6e8d7118d6..07f711d72f 100644 --- a/templates/web/prod/index.html.twig +++ b/templates/web/prod/index.html.twig @@ -288,6 +288,11 @@ From e838b6f1663da49ff33dfbbef1595781d45ea989 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Thu, 23 Nov 2017 16:40:20 +0400 Subject: [PATCH 03/25] Port PHRAS-1577 to 4.1 --- templates/web/prod/WorkZone/Basket.html.twig | 6 +- templates/web/prod/WorkZone/Story.html.twig | 6 +- templates/web/prod/toolbar.html.twig | 62 ++++++++++---------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/templates/web/prod/WorkZone/Basket.html.twig b/templates/web/prod/WorkZone/Basket.html.twig index 36307244cb..31a2b2bceb 100644 --- a/templates/web/prod/WorkZone/Basket.html.twig +++ b/templates/web/prod/WorkZone/Basket.html.twig @@ -41,9 +41,9 @@ {% endif %} {% if app.getAclForUser(app.getAuthenticatedUser()).has_right(constant('\\ACL::BAS_CHUPUB')) %} - + {##} diff --git a/templates/web/prod/WorkZone/Story.html.twig b/templates/web/prod/WorkZone/Story.html.twig index 8c1c3474d2..d3c7bced84 100644 --- a/templates/web/prod/WorkZone/Story.html.twig +++ b/templates/web/prod/WorkZone/Story.html.twig @@ -41,9 +41,9 @@ {% endif %} {% if app.getAclForUser(app.getAuthenticatedUser()).has_right(constant('\\ACL::BAS_CHUPUB')) %} - + {##} diff --git a/templates/web/prod/toolbar.html.twig b/templates/web/prod/toolbar.html.twig index 5cac9201a1..dd4dee0230 100644 --- a/templates/web/prod/toolbar.html.twig +++ b/templates/web/prod/toolbar.html.twig @@ -139,13 +139,13 @@ {{ 'Feedback' | trans }} -
  • -
  • - - - {{ 'action : bridge' | trans }} - -
  • + {#
  • #} + {#
  • #} + {##} + {##} + {#{{ 'action : bridge' | trans }}#} + {##} + {#
  • #}
  • @@ -211,36 +211,36 @@ {% elseif acl.has_right(constant('\\ACL::BAS_CHUPUB')) %}
    - #} + - + {% endif %}
    {% elseif plugins.actionbar is not empty %} From a79b72fbaf7a23de360b3c92734117e3990eb86c Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Fri, 24 Nov 2017 16:22:31 +0400 Subject: [PATCH 04/25] Port PHRAS-1593 --- .bowerrc | 3 +- .../Controller/Prod/ShareController.php | 85 +++++---- .../Phrasea/ControllerProvider/Prod/Share.php | 20 ++- templates/web/prod/Share/record.html.twig | 163 ++++++++++++------ .../Phrasea/Controller/Prod/ShareTest.php | 108 +++++------- 5 files changed, 230 insertions(+), 149 deletions(-) diff --git a/.bowerrc b/.bowerrc index 764e156e8a..bb6d6aafdb 100644 --- a/.bowerrc +++ b/.bowerrc @@ -1,3 +1,4 @@ { - "directory" : "www/bower_components" + "directory" : "www/bower_components", + "timeout": 1200000 } diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php b/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php index 85df3351cf..04b0f00612 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php @@ -23,44 +23,71 @@ class ShareController extends Controller */ public function shareRecord($base_id, $record_id) { - $outputVars = [ - 'isAvailable' => false, - 'preview' => [ - 'permalinkUrl' => '', - 'permaviewUrl' => '', - 'embedUrl' => '', - 'width' => '', - 'height' => '' - ] - ]; $record = new \record_adapter($this->app, \phrasea::sbasFromBas($this->app, $base_id), $record_id); - if (!$this->getAclForUser()->has_access_to_subdef($record, 'preview')) { - $this->app->abort(403); - } + //get list of subdefs + $subdefs = $record->get_subdefs(); - $preview = $record->get_preview(); + $databoxSubdefs = $record->getDatabox()->get_subdef_structure()->getSubdefGroup($record->getType()); + $acl = $this->getAclForUser(); + $subdefList = []; + $defaultKey = null; + foreach ($subdefs as $subdef) { + $subdefName = $subdef->get_name(); + if ($subdefName == 'document') { + if (!$acl->has_right_on_base($record->getBaseId(), \ACL::CANDWNLDHD)) { + continue; + } + $label = $this->app->trans('prod::tools: document'); + } + elseif ($databoxSubdefs->hasSubdef($subdefName)) { + if (!$acl->has_access_to_subdef($record, $subdefName)) { + continue; + } + $label = $databoxSubdefs->getSubdef($subdefName)->get_label($this->app['locale']); + } + else { + // this subdef does no exists anymore in databox structure ? + continue; // don't publish it + } + $value = $subdef->get_name(); + $preview = $record->get_subdef($value); + $defaultKey = $value; // will set a default option if neither preview,thumbnail or document is present - if (null !== $previewLink = $preview->get_permalink()) { - $permalinkUrl = $previewLink->get_url(); - $permaviewUrl = $previewLink->get_page(); - $previewWidth = $preview->get_width(); - $previewHeight = $preview->get_height(); - $embedUrl = $this->app->url('alchemy_embed_view', ['url' => (string)$permalinkUrl]); - - $outputVars = [ - 'isAvailable' => true, - 'preview' => [ + if ( ($previewLink = $preview->get_permalink()) !== null ) { + $permalinkUrl = $previewLink->get_url()->__toString(); + $permaviewUrl = $previewLink->get_page(); + $previewWidth = $preview->get_width(); + $previewHeight = $preview->get_height(); + $embedUrl = $this->app->url('alchemy_embed_view', ['url' => (string)$permalinkUrl]); + $previewData = [ + 'label' => $label, 'permalinkUrl' => $permalinkUrl, 'permaviewUrl' => $permaviewUrl, - 'embedUrl' => $embedUrl, - 'width' => $previewWidth, - 'height' => $previewHeight - ] - ]; + 'embedUrl' => $embedUrl, + 'width' => $previewWidth, + 'height' => $previewHeight + ]; + $subdefList[$value] = $previewData; + } } + // candidates as best default selected option + foreach(["preview", "thumbnail", "document"] as $k) { + if (array_key_exists($k, $subdefList)) { + $defaultKey = $k; + break; + } + } + // if no subdef was sharable, subdefList is empty and defaultKey is null + // the twig MUST handle that + $outputVars = [ + 'isAvailable' => !empty($subdefList), + 'subdefList' => $subdefList, + 'defaultKey' => $defaultKey + ]; + return $this->renderResponse('prod/Share/record.html.twig', $outputVars); } } diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php index e4e58e53b2..d2f1901814 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php @@ -47,10 +47,22 @@ class Share implements ControllerProviderInterface, ServiceProviderInterface $controllers->get('/record/{base_id}/{record_id}/', 'controller.prod.share:shareRecord') ->before(function (Request $request) use ($app, $firewall) { - $firewall->requireRightOnSbas( - \phrasea::sbasFromBas($app, $request->attributes->get('base_id')), - \ACL::BAS_CHUPUB - ); + $socialTools = $app['conf']->get(['registry', 'actions', 'social-tools']); + if($socialTools === "all") { + return; + } + elseif($socialTools === "none") { + $app->abort(403, 'social tools disabled'); + } + elseif($socialTools === "publishers") { + $firewall->requireRightOnSbas( + \phrasea::sbasFromBas($app, $request->attributes->get('base_id')), + \ACL::BAS_CHUPUB + ); + } + else { + throw new \Exception("bad value \"" . $socialTools . "\" for social tools"); + } }) ->bind('share_record'); diff --git a/templates/web/prod/Share/record.html.twig b/templates/web/prod/Share/record.html.twig index 24c26fb200..477f0fe192 100644 --- a/templates/web/prod/Share/record.html.twig +++ b/templates/web/prod/Share/record.html.twig @@ -1,59 +1,122 @@ {% if not isAvailable %}

    {{ 'No permalink available.' | trans }}

    {% else %} - {% if preview.permalinkUrl is not empty %} + {% if subdefList is not empty %} + {% set defKey = defaultKey %}
    -
    -

    - - - {% trans %}Send to Twitter{% endtrans %} - -

    -

    - - - {% trans %}Send to Facebook{% endtrans %} - -

    - -
    -
    - - - -

    - {{ 'previewLinkLabel' | trans }}    - {{ 'copyClipboardLabel' | trans }} -

    -
    -
    - - -

    - {{ 'previewLinkLabel' | trans }}    - {{ 'copyClipboardLabel' | trans }} -

    -
    -
    - {#{% if type == 'image' %}#} - - {% spaceless %} - - {% endspaceless %} -

    - {{ 'previewLinkLabel' | trans }}    - {{ 'copyClipboardLabel' | trans }} -

    -
    - {#{% endif %}#} - +
    +

    + {{ 'share::share-record: advance' | trans }} + + {{ 'share::share-record: select-shared-def' | trans }} + +

    +

    + + + {% trans %}Send to Twitter{% endtrans %} + +

    +

    + + + {% trans %}Send to Facebook{% endtrans %} + +

    + +
    +
    + + + +

    + {{ 'previewLinkLabel' | trans }}    + {{ 'copyClipboardLabel' | trans }} +

    +
    +
    + + +

    + {{ 'previewLinkLabel' | trans }}    + {{ 'copyClipboardLabel' | trans }} +

    +
    +
    + {#{% if type == 'image' %}#} + + {% spaceless %} + + {% endspaceless %} +

    + {{ 'previewLinkLabel' | trans }}    + {{ 'copyClipboardLabel' | trans }} +

    +
    + {#{% endif %}#} +
    + + {% else %}
    {{ 'No URL available' | trans }}
    {% endif %} -{% endif %} +{% endif %} \ No newline at end of file diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php index e8aa79d03d..f3163a99ef 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php @@ -2,6 +2,7 @@ namespace Alchemy\Tests\Phrasea\Controller\Prod; +use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Controller\Prod\ShareController; use Alchemy\Phrasea\ControllerProvider\Prod\Share; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -19,86 +20,63 @@ class ShareTest extends \PhraseanetAuthenticatedWebTestCase /** * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord * @covers Alchemy\Phrasea\Controller\Prod\Share::connect - * @covers Alchemy\Phrasea\Controller\Prod\Share::call */ - public function testMountedRouteSlash() + public function testRouteSlashALL() { - $url = sprintf('/prod/share/record/%d/%d/', self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); - self::$DI['client']->request('GET', $url); - $this->assertTrue(self::$DI['client']->getResponse()->isOk()); + $this->_RouteSlash("all", [0=>true, 1=>true, 2=>true, 3=>true]); } - /** - * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord - * @covers Alchemy\Phrasea\Controller\Prod\Share::connect - */ - public function testRouteSlash() + public function testRouteSlashPublishers() { - $stubbedACL = $this->stubACL(); - - //has_right_on_base return true - $stubbedACL->expects($this->once()) - ->method('has_right_on_sbas') - ->will($this->returnValue(true)); - - //has_access_to_subdef return true - $stubbedACL->expects($this->once()) - ->method('has_access_to_subdef') - ->will($this->returnValue(true)); - - - $url = sprintf('/prod/share/record/%d/%d/', self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); - self::$DI['client']->request('GET', $url); - $this->assertTrue(self::$DI['client']->getResponse()->isOk()); + $this->_RouteSlash("publishers", [0=>false, 1=>true, 2=>false, 3=>true]); + } + public function testRouteSlashNone() + { + $this->_RouteSlash("none", [0=>false, 1=>false, 2=>false, 3=>false]); + } + private function _RouteSlash($setting, $expected) + { + $app = $this->getApplication(); + $_conf = $app['conf']; + $app['conf'] = $this->getMockBuilder('Alchemy\Phrasea\Core\Configuration\PropertyAccess') + ->disableOriginalConstructor() + ->getMock(); + $app['conf'] + ->expects($this->any()) + ->method('get') + ->will($this->returnCallback(function ($param, $default) use ($_conf, $setting) { + switch ($param) { + case ['registry', 'actions', 'social-tools']: + return $setting; + } + return $_conf->get($param, $default); + })); + $result = []; + foreach($expected as $flags=>$v) { + $stubbedACL = $this->stubACL(); + // "has_right_on_sbas" IS checked by the route->before(), the url will return 403 + $stubbedACL->expects($this->any()) + ->method('has_right_on_sbas') + ->will($this->returnValue(($flags & 1) ? true:false)); + // but "has_access_to_subdef" IS NOT checked (the url will return a 200 with a message "no subdef to share") + $stubbedACL->expects($this->any()) + ->method('has_access_to_subdef') + ->will($this->returnValue(($flags & 2) ? true:false)); + $url = sprintf('/prod/share/record/%d/%d/', self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); + self::$DI['client']->request('GET', $url); + $result[$flags] = self::$DI['client']->getResponse()->isOk(); + } + $this->assertEquals($expected, $result); } - /** * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord */ public function testShareRecord() { $share = new ShareController(self::$DI['app']); - /** @var \record_adapter $record_1 */ $record_1 = self::$DI['record_1']; - $response = $share->shareRecord($record_1->getBaseId(), $record_1->getRecordId()); $this->assertTrue($response->isOk()); } - - /** - * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord - */ - public function testShareRecordBadAccess() - { - $share = new ShareController(self::$DI['app']); - - $stubbedACL = $this->getMockBuilder('\ACL') - ->disableOriginalConstructor() - ->getMock(); - - //has_access_to_subdef return false - $stubbedACL->expects($this->once()) - ->method('has_access_to_subdef') - ->will($this->returnValue(false)); - - $aclProvider = $this->getMockBuilder('Alchemy\Phrasea\Authentication\ACLProvider') - ->disableOriginalConstructor() - ->getMock(); - $aclProvider->expects($this->any()) - ->method('get') - ->will($this->returnValue($stubbedACL)); - - self::$DI['app']['acl'] = $aclProvider; - - try { - $share->shareRecord(self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); - } catch (HttpException $exception) { - $this->assertEquals(403, $exception->getStatusCode()); - - return; - } - - $this->fail('An access denied exception should have been thrown.'); - } } From cc2f919fe029f32619e34fb200ae448d66879368 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Fri, 24 Nov 2017 16:41:22 +0400 Subject: [PATCH 05/25] dump locales --- resources/locales/messages.de.xlf | 37 +++++++++++++++++++---------- resources/locales/messages.en.xlf | 37 +++++++++++++++++++---------- resources/locales/messages.fr.xlf | 37 +++++++++++++++++++---------- resources/locales/messages.nl.xlf | 37 +++++++++++++++++++---------- resources/locales/validators.de.xlf | 2 +- resources/locales/validators.en.xlf | 2 +- resources/locales/validators.fr.xlf | 2 +- resources/locales/validators.nl.xlf | 2 +- 8 files changed, 100 insertions(+), 56 deletions(-) diff --git a/resources/locales/messages.de.xlf b/resources/locales/messages.de.xlf index c2aacbe27e..6b031485e7 100644 --- a/resources/locales/messages.de.xlf +++ b/resources/locales/messages.de.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -2265,7 +2265,7 @@ Detailed view URL Detailansicht URL - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2580,7 +2580,7 @@ Embed code Embed-Code - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4245,7 +4245,7 @@ No URL available keine verfügbare URL - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5461,7 +5461,7 @@ Resource URL Resource URL - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5739,12 +5739,12 @@ Send to Facebook Auf Facebook teilen - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Auf Twitter teilen - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9325,9 +9325,9 @@ copyClipboardLabel in der Zwischenablage kopieren - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10652,9 +10652,9 @@ previewLinkLabel ansichten - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10967,6 +10967,7 @@ prod::tools: document Dokument + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12107,6 +12108,16 @@ Test E-Mail Überprüfungen web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport Sport diff --git a/resources/locales/messages.en.xlf b/resources/locales/messages.en.xlf index 6e4ee0b7ed..e255caea7f 100644 --- a/resources/locales/messages.en.xlf +++ b/resources/locales/messages.en.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -2265,7 +2265,7 @@ Detailed view URL URL of the detailed view - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2580,7 +2580,7 @@ Embed code Embed code - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4245,7 +4245,7 @@ No URL available No URL available - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5461,7 +5461,7 @@ Resource URL Resource URL - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5739,12 +5739,12 @@ Send to Facebook Send to Facebook - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Send to Twitter - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9326,9 +9326,9 @@ copyClipboardLabel Copy to clipboard - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10653,9 +10653,9 @@ previewLinkLabel Preview - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10968,6 +10968,7 @@ prod::tools: document Document + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12108,6 +12109,16 @@ E-mails send test web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport sport diff --git a/resources/locales/messages.fr.xlf b/resources/locales/messages.fr.xlf index 120dd38604..ddb08c69b6 100644 --- a/resources/locales/messages.fr.xlf +++ b/resources/locales/messages.fr.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -2265,7 +2265,7 @@ Detailed view URL URL de la vue détaillée - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2580,7 +2580,7 @@ Embed code Code d'intégration (Embed code) - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4245,7 +4245,7 @@ No URL available Aucune URL de disponible - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5463,7 +5463,7 @@ Pour les utilisateurs authentifiés, la demande de validation est également dis Resource URL URL de la ressource - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5741,12 +5741,12 @@ Pour les utilisateurs authentifiés, la demande de validation est également dis Send to Facebook Envoyer vers Facebook - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Envoyer vers Twitter - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9329,9 +9329,9 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le copyClipboardLabel Copier dans le presse-papier - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10656,9 +10656,9 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le previewLinkLabel Prévisualiser - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10971,6 +10971,7 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le prod::tools: document Document + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12111,6 +12112,16 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le Tests d'envois d'e-mails web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport sport diff --git a/resources/locales/messages.nl.xlf b/resources/locales/messages.nl.xlf index f368872247..deabb6ae7a 100644 --- a/resources/locales/messages.nl.xlf +++ b/resources/locales/messages.nl.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -2269,7 +2269,7 @@ Detailed view URL Gedetailleerde weergave URL - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2584,7 +2584,7 @@ Embed code Sluit de code in - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4249,7 +4249,7 @@ No URL available Geen URL beschikbaar - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5465,7 +5465,7 @@ Resource URL Bron URL - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5743,12 +5743,12 @@ Send to Facebook Verstuur naar Facebook - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Verstuur naar Twitter - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9329,9 +9329,9 @@ copyClipboardLabel copyClipboardLabel - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10656,9 +10656,9 @@ previewLinkLabel previewLinkLabel - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10971,6 +10971,7 @@ prod::tools: document prod::tools: document + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12111,6 +12112,16 @@ Testen voor het versturen van mail web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport sport diff --git a/resources/locales/validators.de.xlf b/resources/locales/validators.de.xlf index e9542f0cc8..c38d4d62b3 100644 --- a/resources/locales/validators.de.xlf +++ b/resources/locales/validators.de.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/resources/locales/validators.en.xlf b/resources/locales/validators.en.xlf index 324bce198f..8e508b21ff 100644 --- a/resources/locales/validators.en.xlf +++ b/resources/locales/validators.en.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/resources/locales/validators.fr.xlf b/resources/locales/validators.fr.xlf index 6446b7e611..574553b0a6 100644 --- a/resources/locales/validators.fr.xlf +++ b/resources/locales/validators.fr.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/resources/locales/validators.nl.xlf b/resources/locales/validators.nl.xlf index 7077d6f7e7..8937ac1dfa 100644 --- a/resources/locales/validators.nl.xlf +++ b/resources/locales/validators.nl.xlf @@ -1,6 +1,6 @@ - +
    The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. From 3200760430277d5288618a47631b1184125a2a3f Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Mon, 11 Dec 2017 17:50:49 +0400 Subject: [PATCH 06/25] fix makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d644c078c7..52f1317967 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ install: make install_assets install_composer: - composer + composer install install_asset_dependencies: npm install From 5f2ce74956055a3b8141c1749fc2e621b9987c91 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Tue, 12 Dec 2017 11:56:49 +0400 Subject: [PATCH 07/25] fix context-menu help --- resources/www/common/js/components/common.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/www/common/js/components/common.js b/resources/www/common/js/components/common.js index 5f5db50428..ee198857d8 100644 --- a/resources/www/common/js/components/common.js +++ b/resources/www/common/js/components/common.js @@ -31,11 +31,11 @@ var commonModule = (function ($, p4) { $(this).removeClass('context-menu-item-hover'); }); - $('#help-trigger').contextMenu('#mainMenu .helpcontextmenu', {openEvt: 'click', dropDown: true, theme: 'vista', dropDown: true, - showTransition: 'slideDown', - hideTransition: 'hide', - shadow: false - }); + // $('#help-trigger').contextMenu('#mainMenu .helpcontextmenu', {openEvt: 'click', dropDown: true, theme: 'vista', dropDown: true, + // showTransition: 'slideDown', + // hideTransition: 'hide', + // shadow: false + // }); }); function showOverlay(n, appendto, callback, zIndex) { From a099ec33f3a29d7c074e83364474218b519c716e Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Tue, 12 Dec 2017 15:13:55 +0400 Subject: [PATCH 08/25] modify icons for document types --- .../www/common/images/icons/icon_audio.png | Bin 670 -> 894 bytes .../www/common/images/icons/icon_document.png | Bin 3309 -> 382 bytes .../www/common/images/icons/icon_image.png | Bin 714 -> 1097 bytes .../www/common/images/icons/icon_video.png | Bin 478 -> 764 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/www/common/images/icons/icon_audio.png b/resources/www/common/images/icons/icon_audio.png index 7765028fddee323b80e60e0dda217768f55af357..2f6ae11e3400222292078cf844dfe3835a3431fa 100644 GIT binary patch delta 870 zcmV-s1DX7u1^xyhiBL{Q4GJ0x0000DNk~Le0001h0001h2m=5B0QBII`H>+fe*i*I zOjJc4*I@tu|Ht*$R^f;&+G#v>exw-SrWaN@%s=L)p`g&7H;D~19n%TNHvj0Dhse;5j2I)(!D z%xQo|N#8f_&MyUUopsX4lwN z6d?G}$U46$K%gL7`1$3J-&9ReUwfkFVN%wt#_z&8X70T}Y4a(MuqX9wj0 z{406|0r2+#0?=d`q5yzz2LlA4&hZ2i07K3xlmJjUr%(bwqX8(#e+)zbsskV+TOk7A zGQ!aT@H+wEhw$(NXjcpmM(}V9zmUMMWavvN{8|own4q6#@W(0qd5%s{)EVj9B$}$sVOkx2q*Y@#6Jb#CVkNJGl*5w8wY@LrVe@x5r&t zIF>p&qD?GfBMc7L#`7sxn*#8>m1v*qH+$T%l`G!VuxB${%;S5Wu%E5O4kRyuJ^I1O zsGSBVe0u~nHaj%HKYK(0JUX0U0AKbv5KiW2cncleYWgc3JaWh(KTqHTkMNOC_|PkS w?Duw?aO+QhN55gC*VFia48LQ?|33s60Ld655&HViM*si-07*qoM6N<$g7R#ia{vGU delta 644 zcmV-~0(<@b2A%~WiBL{Q4GJ0x0000DNk~Le0000G0000G2nGNE03Y-JVUZyxe*!>B zL_t(|+I&+@Xj4HD{x*q)+Zf}Q%!Z2c{@AvzM0vX9nziX zUj<+%17D00l!?pyBPGI^(keSZf220R`6B15QbnqE!WYU%28QK`Qi?#0ksq7GP3Srt zLua&Isb9aH#4FBox~{;EW_*PvbtAvN_uM)Xx8iN484Q2?fuX4kp3gf#H6DL9 zp&p2l%P6n_CN~9<+!$0~K@%@tLOgNxkVZxyVDFyYvNcwzgm9ftMvONEYOa=^p267D zaoKTgb^=e+rl9SlSZgq`6RpfdNQP3GmWjWq81U zQe5t-_WVyv!++j-FA*EQzdL;Y?*GR=?JoQKUm$@&%ZLB!zBEQ(km;VTelF{r5}E){ C+^c~A literal 3309 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 diff --git a/resources/www/common/images/icons/icon_image.png b/resources/www/common/images/icons/icon_image.png index 5f9d51c1085537f3bce451f94b68e898ad04a06d..4aa5270af43e1ae68578322d6cd4bdb4e16573d4 100644 GIT binary patch delta 1075 zcmV-31kC%&1<42@iBL{Q4GJ0x0000DNk~Le0001h0001h2m=5B0QBII`H>+fe*ipC zOjJexx&Z(G|NqNC|J{K9+<*W3@Bh9K|L(v4)L{R|F#p3K|MuVi<)8oQumAGT|JZQ< z&`|&3kN@SM|NsBzkQLGZ000zpQchF<|NsC0|NsC0|NsC0|NsC0|Nj6_Pv;Q;00VAgPO_zfB)-r;@E9kfdaYotd)AmOH69#q&O6a!+j0rKH7$3 zYvSSgDwd&r$mt7U9{R+`KL9!O3i$+>hkh}C0*Ik!h~bW10dO!w=eYF-_~;FQZ-Czn zpb(LF0^rgbSVP=Ya{z4_?8D5wB>*4c5N2rypbVUah?{{o;p18Aya)BvJTi;6RM1ZISq`p{xUvCouqVv&0 z9fEY%z_ar8g(Z4WN+bURQH2%;6UhUnG~@hvL4aW5bPu9Sa3J&&2%g|UbP0~{b8%%B z98;HbXMplpih|e*a+W%Mp1&<$E6I@?L7QB+ zG29AzkY54}{Hmp(2YDsHz}y}$g9YHK1SjVQ7=2U5WB`~50H5gFVl(7~34jn z!hP2|@vqMx3pUzW8^iswA+cM+pCWabY#Xu)z t=cC`Omj(;lp1!xbLwao=ss9Qv07u>~z^H}S@&Et;2>?k&PDHLkV1lC$_<;Zb delta 689 zcmV;i0#5zO2+9Q^iBL{Q4GJ0x0000DNk~Le0000G0000G2nGNE03Y-JVUZyxe*$bt zL_t(|+Kf}nZWA#SJ$_6cO_~%$iBPJbN);+E@meD!5Z%B(z?bkf?7D_6s)SfjQKY7# zl~}Yi5~Q!0G&Gsacx-d+Nt$+tJ@%C?pX1|m@33C9yI3j}-)gOyQW;BA#gkDYMoGex zB;{%9hT=*o?#@^X--O^+N@-=Ke=_ri*6%u}fHe$S3m6+fi!!o;rkDW~g*IT;VA2?4 zsInoXTkJ;$@7EK@fZ0NVY7nCnmSBvgEltr-q%pqUQdjW+D@zvAF%ci!e5VoO`Ss7p z27fVFT*B(sGERqrZnLOY3Yf13czJscYn%I6-%G)HF<0O@sI9cVqyKdce>zhLuI%D* z^BO+=Y=Ci&*AE(K&ILH=9^qkg2D>LQ`53Q34U!A5e*m#iqZeGe+oljS$#3Zk2Ar~J@5`&?DrVD{XTj_PM{pDlOx#d5ISzt zG2@5Jj3e+0CdDC{!lQ*v7~Vycl3_cY96UZ?k}ZJOkR=`D*?Tp8g5)W=zJY4t3_U6d zrGG${Qe-20F53~A_zSdB{>@I6e?lM>o-Ax&ws?k28HC3}l5bJHe-S_wnFmf(_{*d` zUwZ-vbVFwby>RH+y+r!vZWbVd3+_9Rb3c&YGd|gL;3$l9KiIV1x#Xy|3RFx}C9Vr8 zs1C$93-t5!qtv_U4*KpQ%VSU${yDgi^LnL*`phik@kxYu5aWLH=_Q%Z@PF-}00RK? X@;f`1W+|-z0000<2SrXqu0mjf1tK}V diff --git a/resources/www/common/images/icons/icon_video.png b/resources/www/common/images/icons/icon_video.png index b97bb59f60779d5e6a53f421e69f1dc7d3de69cc..14c917bee001c097416e9f0e4e7d117dd59773e6 100644 GIT binary patch delta 739 zcmcb|{D)PsGr-TCmrII^fq{Y7)59eQNH>5m2Q!fT@?hf6iHhp=4E6y&A+G<^82$sn z&Hev3)&Kwc{(phM{~m|`Z|?uERQSKS;s3Gu|K}(C-_!s9(fR)i68<+E{GS%^|LFYx zD+~UgUk}vhweqMb&`i;iAirRcIp}~v`)2Jc1_mZ0PZ!6Kid%1PpDt=P;9(8uyixBE zEa!Rne|@&6b?(eGrn;D)X^CrRevDMupz1v>x99LmhdX!DJa4YCtJD8}``?I}Kbx}O<`LCDefy@2Hk_XPc zU&)g2y*h+p!+uvocA3AEdl-+`rv^Km*mp!gV4Lw~W|nupYZ(siE|zvU(s-9iAav6K zW~K8hG912W%JOuq4|ZVGoGPWDu(pDmdC9c(jt%u+s#IAfTt4K$uqo@>&xSLrYV{O$ z=TBs3D9I~gn2?rd#c*Y>H`@ZKU!4uoYno@XIDFe6%y2`m&V-@1Us0%G|4Bi1i^uCP zA7PN{zHRfc;n*{#0*wWmcRCAmb-ZGTVBpbzaQ$|PXaFM!In3Ym@Vw+j^|e-72~~}m z*8lb>)>=L)iqz9__^cJYy*oSdwXpj7-xF=B-^nd|KfCDi_rLeQ{9Vq#%n)UxXf5{U Sh6*r^F?hQAxvXOT8iBL{Q4GJ0x0000DNk~Le0000G0000G2nGNE03Y-JVUZyxe*u6= zL_t(|+MH8CO2bePeUtvSE`%0bSa;bA;?`YOBDnDe9;Ngsp1>>Q3gS*gx=|=aX)tZm zHvf+^KS>)zZE(UcKa)3a=Fd!MdU<_Lzzsz1&ra#J*8?+?sJgaRobV@+L6YF=;Sqtj zjRuPj3zR%m=wH${1|15Ju!E_be`TgdqR@A1kx5NK=^Km2+$fmwnPo_wjV<%IBGBN` zo=_jWTrQDYhn#t29ml3*jf5bqgMZ4rSY&X{DV4qt9U-iG5R2X&rD?<{AK`H9^Ljg9 zt6oRs^A7qKoGj$i3vFl<3qlHgeX6tyzhRQIfBbeAVWAf5BW+C73zA zZ_#T4JBW Date: Tue, 12 Dec 2017 18:20:16 +0100 Subject: [PATCH 09/25] PHRAS-1719 Add presets selection on subdef admin page --- .../Controller/Admin/SubdefsController.php | 459 ++++++++- .../Phrasea/Databox/Subdef/SubdefPreset.php | 46 + .../Databox/Subdef/SubdefPresetProvider.php | 19 + lib/Alchemy/Phrasea/Media/Subdef/Subdef.php | 2 + lib/classes/databox/subdef.php | 153 ++- lib/classes/databox/subdefsStructure.php | 15 +- resources/www/admin/styles/main.scss | 95 +- templates/web/admin/subdefs.html.twig | 872 +++++++++++------- .../Phrasea/Controller/Admin/SubdefsTest.php | 51 +- 9 files changed, 1229 insertions(+), 483 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Databox/Subdef/SubdefPreset.php create mode 100644 lib/Alchemy/Phrasea/Databox/Subdef/SubdefPresetProvider.php diff --git a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php index 166ee61c56..c68c90922f 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php @@ -12,8 +12,14 @@ namespace Alchemy\Phrasea\Controller\Admin; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Databox\SubdefGroup; +use Alchemy\Phrasea\Media\Subdef\Subdef; +use Alchemy\Phrasea\Media\Type\Type; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Alchemy\Phrasea\Media\Subdef\Image; +use Alchemy\Phrasea\Media\Subdef\Video; +use Alchemy\Phrasea\Media\Subdef\Audio; +use Alchemy\Phrasea\Media\Subdef\Gif; class SubdefsController extends Controller { @@ -23,10 +29,14 @@ class SubdefsController extends Controller */ function indexAction($sbas_id) { $databox = $this->findDataboxById((int) $sbas_id); + $config = $this->getConfiguration(); + $subviews_mapping = $this->getSubviewsMapping(); return $this->render('admin/subdefs.html.twig', [ 'databox' => $databox, 'subdefs' => $databox->get_subdef_structure(), + 'config' => $config, + 'subviews_mapping' => $subviews_mapping ]); } @@ -43,7 +53,7 @@ class SubdefsController extends Controller $databox = $this->findDataboxById((int) $sbas_id); - $add_subdef = ['class' => null, 'name' => null, 'group' => null]; + $add_subdef = ['class' => null, 'name' => null, 'group' => null, 'mediaType' => null, 'presets' => null]; foreach ($add_subdef as $k => $v) { if (!isset($toadd_subdef[$k]) || trim($toadd_subdef[$k]) === '') { unset($add_subdef[$k]); @@ -58,7 +68,7 @@ class SubdefsController extends Controller $name = $delete_subef[1]; $subdefs = $databox->get_subdef_structure(); $subdefs->delete_subdef($group, $name); - } elseif (count($add_subdef) === 3) { + } elseif (count($add_subdef) === 5) { $subdefs = $databox->get_subdef_structure(); $group = $add_subdef['group']; @@ -66,11 +76,84 @@ class SubdefsController extends Controller $unicode = $this->app['unicode']; $name = $unicode->remove_nonazAZ09($add_subdef['name'], false); $class = $add_subdef['class']; + $preset = $add_subdef['presets']; + $mediatype = $add_subdef['mediaType']; + + $subdefs->add_subdef($group, $name, $class, $mediatype, $preset); + + if ($preset !== "Choose") { + $options = []; + + $config = $this->getConfiguration(); + + //On applique directement les valeurs du preset à la sous def + switch($mediatype) { + case Subdef::TYPE_IMAGE : + $options["path"] = ""; + $options["meta"] = true; + $options["mediatype"] = $mediatype; + $options[Image::OPTION_SIZE] = $config["image"]["definitions"][$preset][Image::OPTION_SIZE]; + $options["dpi"] = $config["image"]["definitions"][$preset][Image::OPTION_RESOLUTION]; + $options[Image::OPTION_STRIP] = $config["image"]["definitions"][$preset][Image::OPTION_STRIP]; + $options[Image::OPTION_FLATTEN] = $config["image"]["definitions"][$preset][Image::OPTION_FLATTEN]; + $options[Image::OPTION_QUALITY] = $config["image"]["definitions"][$preset][Image::OPTION_QUALITY]; + $options[Image::OPTION_ICODEC] = $config["image"]["definitions"][$preset][Image::OPTION_ICODEC]; + foreach($config["image"]["definitions"][$preset][Subdef::OPTION_DEVICE] as $devices) { + $options[Subdef::OPTION_DEVICE][] = $devices; + } + break; + case Subdef::TYPE_VIDEO : + $options["path"] = ""; + $options["meta"] = true; + $options["mediatype"] = $mediatype; + $options[Video::OPTION_AUDIOBITRATE] = $config["video"]["definitions"][$preset][Video::OPTION_AUDIOBITRATE]; + $options[Video::OPTION_AUDIOSAMPLERATE] = $config["video"]["definitions"][$preset][Video::OPTION_AUDIOSAMPLERATE]; + $options[Video::OPTION_BITRATE] = $config["video"]["definitions"][$preset][Video::OPTION_BITRATE]; + $options[Video::OPTION_GOPSIZE] = $config["video"]["definitions"][$preset][Video::OPTION_GOPSIZE]; + $options[Video::OPTION_SIZE] = $config["video"]["definitions"][$preset][Video::OPTION_SIZE]; + $options[Video::OPTION_FRAMERATE] = $config["video"]["definitions"][$preset][Video::OPTION_FRAMERATE]; + $options[Video::OPTION_VCODEC] = $config["video"]["definitions"][$preset][Video::OPTION_VCODEC]; + $options[Video::OPTION_ACODEC] = $config["video"]["definitions"][$preset][Video::OPTION_ACODEC]; + foreach($config["video"]["definitions"][$preset][Subdef::OPTION_DEVICE] as $devices) { + $options[Subdef::OPTION_DEVICE][] = $devices; + } + break; + case Subdef::TYPE_FLEXPAPER : + $options["path"] = ""; + $options["meta"] = true; + $options["mediatype"] = $mediatype; + foreach($config["document"]["definitions"][$preset]["devices"] as $devices) { + $options["devices"][] = $devices; + } + break; + case Subdef::TYPE_ANIMATION : + $options["path"] = ""; + $options["meta"] = true; + $options["mediatype"] = $mediatype; + $options[Gif::OPTION_SIZE] = $config["gif"]["definitions"][$preset][Gif::OPTION_SIZE]; + $options[Gif::OPTION_DELAY] = $config["gif"]["definitions"][$preset][Gif::OPTION_DELAY]; + foreach($config["gif"]["definitions"][$preset][Subdef::OPTION_DEVICE] as $devices) { + $options[Subdef::OPTION_DEVICE][] = $devices; + } + break; + case Subdef::TYPE_AUDIO : + $options["path"] = ""; + $options["meta"] = true; + $options["mediatype"] = $mediatype; + $options[Audio::OPTION_AUDIOBITRATE] = $config["audio"]["definitions"][$preset][Audio::OPTION_AUDIOBITRATE]; + $options[Audio::OPTION_AUDIOSAMPLERATE] = $config["audio"]["definitions"][$preset][Audio::OPTION_AUDIOSAMPLERATE]; + $options[Audio::OPTION_ACODEC] = $config["audio"]["definitions"][$preset][Audio::OPTION_ACODEC]; + foreach($config["audio"]["definitions"][$preset][Subdef::OPTION_DEVICE] as $devices) { + $options[Subdef::OPTION_DEVICE][] = $devices; + } + break; + } + + $subdefs->set_subdef($group, $name, $class, false, $options, [], $preset); + } - $subdefs->add_subdef($group, $name, $class); } else { $subdefs = $databox->get_subdef_structure(); - $this->updateSubdefGroups($subdefs, $request); foreach ($Parmsubdefs as $post_sub) { @@ -81,6 +164,7 @@ class SubdefsController extends Controller $group = $post_sub_ex[0]; $name = $post_sub_ex[1]; + $preset = $request->request->get($post_sub . '_presets'); $class = $request->request->get($post_sub . '_class'); $downloadable = $request->request->get($post_sub . '_downloadable'); $orderable = $request->request->get($post_sub . '_orderable'); @@ -96,7 +180,6 @@ class SubdefsController extends Controller $options[$def] = $parm_loc; } - $mediatype = $request->request->get($post_sub . '_mediatype'); $media = $request->request->get($post_sub . '_' . $mediatype, []); @@ -110,8 +193,7 @@ class SubdefsController extends Controller } $labels = $request->request->get($post_sub . '_label', []); - - $subdefs->set_subdef($group, $name, $class, $downloadable, $options, $labels, $orderable); + $subdefs->set_subdef($group, $name, $class, $downloadable, $options, $labels, $preset, $orderable); } } @@ -120,36 +202,389 @@ class SubdefsController extends Controller ]); } + /** + * @return array + */ + protected function getSubviewsMapping() + { + $mapping = array( + Type::TYPE_IMAGE => array(Subdef::TYPE_IMAGE), + Type::TYPE_VIDEO => array(Subdef::TYPE_IMAGE, Subdef::TYPE_VIDEO, Subdef::TYPE_ANIMATION), + Type::TYPE_AUDIO => array(Subdef::TYPE_IMAGE, Subdef::TYPE_AUDIO), + Type::TYPE_DOCUMENT => array(Subdef::TYPE_IMAGE, Subdef::TYPE_FLEXPAPER), + Type::TYPE_FLASH => array(Subdef::TYPE_IMAGE) + ); + + return $mapping; + } + /** * Update Databox subdefsStructure DOM according to defined groups. * * @param \databox_subdefsStructure $subdefs * @param Request $request */ - private function updateSubdefGroups(\databox_subdefsStructure $subdefs, Request $request) + protected function updateSubdefGroups(\databox_subdefsStructure $subdefs, Request $request) { $subdefsGroups = $request->request->get('subdefsgroups', []); $changedGroups = []; - /** @var SubdefGroup $subdefsGroup */ foreach ($subdefs as $groupName => $subdefsGroup) { $documentOrderable = isset($subdefsGroups[$groupName]['document_orderable']) ? \p4field::isyes($subdefsGroups[$groupName]['document_orderable']) : false; - if ($subdefsGroup->isDocumentOrderable() !== $documentOrderable) { if ($documentOrderable) { $subdefsGroup->allowDocumentOrdering(); } else { $subdefsGroup->disallowDocumentOrdering(); } - $changedGroups[] = $subdefsGroup; } } - if ($changedGroups) { $subdefs->updateSubdefGroups($changedGroups); } } + + /** + * @return array + */ + protected function getConfiguration() + { + $config = array( + Subdef::TYPE_IMAGE => array( + "definitions" => array( + "JPG" => null, + "160px JPG" => array( + Image::OPTION_SIZE => "160", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "jpeg", + Subdef::OPTION_DEVICE => ["all"] + ), + "320 px JPG (thumbnail Phraseanet)" => array( + Image::OPTION_SIZE => "320", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "jpeg", + Subdef::OPTION_DEVICE => ["all"] + ), + "640px JPG" => array( + Image::OPTION_SIZE => "640", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "jpeg", + Subdef::OPTION_DEVICE => ["all"] + ), + "1280px JPG (preview Phraseanet)" => array( + Image::OPTION_SIZE => "1280", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "jpeg", + Subdef::OPTION_DEVICE => ["all"] + ), + "2560px JPG" => array( + Image::OPTION_SIZE => "2560", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "jpeg", + Subdef::OPTION_DEVICE => ["all"] + ), + "PNG" => null, + "160px PNG 8 bits" => array( + Image::OPTION_SIZE => "160", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "png", + Subdef::OPTION_DEVICE => ["all"] + ), + "320px PNG 8 bits" => array( + Image::OPTION_SIZE => "320", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "png", + Subdef::OPTION_DEVICE => ["all"] + ), + "640px PNG 8 bits" => array( + Image::OPTION_SIZE => "640", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "png", + Subdef::OPTION_DEVICE => ["all"] + ), + "1280px PNG 8 bits" => array( + Image::OPTION_SIZE => "1280", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "png", + Subdef::OPTION_DEVICE => ["all"] + ), + "2560px PNG 8 bits" => array( + Image::OPTION_SIZE => "2560", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "png", + Subdef::OPTION_DEVICE => ["all"] + ), + "TIFF" => null, + "1280 TIFF" => array( + Image::OPTION_SIZE => "1280", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "tiff", + Subdef::OPTION_DEVICE => ["all"] + ), + "2560px TIFF" => array( + Image::OPTION_SIZE => "2560", + Image::OPTION_RESOLUTION => "75", + Image::OPTION_STRIP => "yes", + Image::OPTION_FLATTEN => "yes", + Image::OPTION_QUALITY => "75", + Image::OPTION_ICODEC => "tiff", + Subdef::OPTION_DEVICE => ["all"] + ), + ), + "form" => array( + Image::OPTION_SIZE => "slide", + Image::OPTION_RESOLUTION => "slide", + Image::OPTION_STRIP => "radio", + Image::OPTION_FLATTEN => "radio", + Image::OPTION_QUALITY => "slide", + Image::OPTION_ICODEC => "select", + Subdef::OPTION_DEVICE => "checkbox", + ), + ), + Subdef::TYPE_VIDEO => array( + "definitions" => array( + "video codec H264" => null, + "144P H264 128 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "128", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "256", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "240P H264 256 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "256", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "426", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "360P H264 576 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "576", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "480", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libtheora", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "480P H264 750 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "750", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "854", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "720P H264 1492 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "1492", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1280", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "1080P H264 2420 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "2420", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1920", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "video codec libvpx" => null, + "144P webm 128 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "128", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "256", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "240P webm 256 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "256", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "426", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "360P webm 576 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "576", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "480", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "480P webm 750 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "750", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "854", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "720P webm 1492 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "1492", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1280", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + "1080P webm 2420 kbps ACC 128kbps" => array( + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "2420", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1920", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfaac", + Subdef::OPTION_DEVICE => ["all"] + ), + ), + "form" => array( + Video::OPTION_AUDIOBITRATE => "slide", + Video::OPTION_AUDIOSAMPLERATE => "select", + Video::OPTION_BITRATE => "slide", + Video::OPTION_GOPSIZE => "slide", + Video::OPTION_SIZE => "slide", + Video::OPTION_FRAMERATE => "slide", + Video::OPTION_VCODEC => "select", + Video::OPTION_ACODEC => "select", + Subdef::OPTION_DEVICE => "checkbox", + ), + ), + Subdef::TYPE_ANIMATION => array( + "definitions" => array( + "256 px fast 200 ms" => array( + Gif::OPTION_SIZE => "256", + Gif::OPTION_DELAY => "200", + Subdef::OPTION_DEVICE => ["all"] + ), + "256 px very fast 120 ms" => array( + Gif::OPTION_SIZE => "256", + Gif::OPTION_DELAY => "120", + Subdef::OPTION_DEVICE => ["all"] + ), + "320 px fast 200 ms" => array( + Gif::OPTION_SIZE => "320", + Gif::OPTION_DELAY => "200", + Subdef::OPTION_DEVICE => ["all"] + ), + ), + "form" => array( + Gif::OPTION_SIZE => "slide", + Gif::OPTION_DELAY => "slide", + Subdef::OPTION_DEVICE => "checkbox", + ), + ), + Subdef::TYPE_AUDIO => array( + "definitions" => array( + "Low AAC 96 kbit/s" => array( + Audio::OPTION_AUDIOBITRATE => "100", + Audio::OPTION_AUDIOSAMPLERATE => "8000", + Audio::OPTION_ACODEC => "libmp3lame", + Subdef::OPTION_DEVICE => ["all"] + ), + "Normal AAC 128 kbit/s" => array( + Audio::OPTION_AUDIOBITRATE => "180", + Audio::OPTION_AUDIOSAMPLERATE => "44100", + Audio::OPTION_ACODEC => "libmp3lame", + Subdef::OPTION_DEVICE => ["all"] + ), + "High AAC 320 kbit/s" => array( + Audio::OPTION_AUDIOBITRATE => "230", + Audio::OPTION_AUDIOSAMPLERATE => "50000", + Audio::OPTION_ACODEC => "libmp3lame", + Subdef::OPTION_DEVICE => ["all"] + ), + ), + "form" => array( + Audio::OPTION_AUDIOBITRATE => "slide", + Audio::OPTION_AUDIOSAMPLERATE => "select", + Audio::OPTION_ACODEC => "select", + Subdef::OPTION_DEVICE => "checkbox", + ), + ), + Subdef::TYPE_FLEXPAPER => array( + "definitions" => array( + ), + "form" => array(), + ), + ); + + return $config; + } } diff --git a/lib/Alchemy/Phrasea/Databox/Subdef/SubdefPreset.php b/lib/Alchemy/Phrasea/Databox/Subdef/SubdefPreset.php new file mode 100644 index 0000000000..7a954badc7 --- /dev/null +++ b/lib/Alchemy/Phrasea/Databox/Subdef/SubdefPreset.php @@ -0,0 +1,46 @@ +mediaType = (string) $mediaType; + $this->definitions = $definitions; + } + /** + * @return string + */ + public function getMediaType() + { + return $this->label; + } + /** + * @return array + */ + public function getDefinitions() + { + return $this->definitions; + } +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Databox/Subdef/SubdefPresetProvider.php b/lib/Alchemy/Phrasea/Databox/Subdef/SubdefPresetProvider.php new file mode 100644 index 0000000000..2f6c989ad8 --- /dev/null +++ b/lib/Alchemy/Phrasea/Databox/Subdef/SubdefPresetProvider.php @@ -0,0 +1,19 @@ +presets[$type])) { + throw new \InvalidArgumentException('Invalid type'); + } + return $this->presets[$type]; + } +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Media/Subdef/Subdef.php b/lib/Alchemy/Phrasea/Media/Subdef/Subdef.php index 339d50002f..3853958f4c 100644 --- a/lib/Alchemy/Phrasea/Media/Subdef/Subdef.php +++ b/lib/Alchemy/Phrasea/Media/Subdef/Subdef.php @@ -15,6 +15,8 @@ use MediaAlchemyst\Specification\SpecificationInterface; interface Subdef { + const OPTION_DEVICE = 'devices'; + const TYPE_IMAGE = 'image'; const TYPE_ANIMATION = 'gif'; const TYPE_VIDEO = 'video'; diff --git a/lib/classes/databox/subdef.php b/lib/classes/databox/subdef.php index 1cac20b970..885685ef89 100644 --- a/lib/classes/databox/subdef.php +++ b/lib/classes/databox/subdef.php @@ -7,40 +7,18 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - +use Alchemy\Phrasea\Media\Subdef\Image; use Alchemy\Phrasea\Media\Subdef\Audio; +use Alchemy\Phrasea\Media\Subdef\Video; use Alchemy\Phrasea\Media\Subdef\FlexPaper; use Alchemy\Phrasea\Media\Subdef\Gif; -use Alchemy\Phrasea\Media\Subdef\Image; use Alchemy\Phrasea\Media\Subdef\Unknown; use Alchemy\Phrasea\Media\Subdef\Subdef as SubdefSpecs; -use Alchemy\Phrasea\Media\Subdef\Video; use Alchemy\Phrasea\Media\Type\Type as SubdefType; use MediaAlchemyst\Specification\SpecificationInterface; use Symfony\Component\Translation\TranslatorInterface; - class databox_subdef { - const CLASS_THUMBNAIL = 'thumbnail'; - const CLASS_PREVIEW = 'preview'; - const CLASS_DOCUMENT = 'document'; - - const DEVICE_ALL = 'all'; - const DEVICE_HANDHELD = 'handheld'; - const DEVICE_PRINT = 'print'; - const DEVICE_PROJECTION = 'projection'; - const DEVICE_SCREEN = 'screen'; - const DEVICE_TV = 'tv'; - - protected static $mediaTypeToSubdefTypes = [ - SubdefType::TYPE_AUDIO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_AUDIO], - SubdefType::TYPE_DOCUMENT => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_FLEXPAPER], - SubdefType::TYPE_FLASH => [SubdefSpecs::TYPE_IMAGE], - SubdefType::TYPE_IMAGE => [SubdefSpecs::TYPE_IMAGE], - SubdefType::TYPE_VIDEO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_VIDEO, SubdefSpecs::TYPE_ANIMATION], - SubdefType::TYPE_UNKNOWN => [SubdefSpecs::TYPE_IMAGE] - ]; - /** * The class type of the subdef * Is null or one of the CLASS_* constants @@ -51,52 +29,61 @@ class databox_subdef protected $devices = []; protected $name; protected $path; + protected $preset; protected $subdef_group; protected $labels = []; - protected $downloadable; - protected $translator; - /** * @var bool */ private $requiresMetadataUpdate; + protected $downloadable; + protected $translator; + protected static $mediaTypeToSubdefTypes = [ + SubdefType::TYPE_AUDIO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_AUDIO], + SubdefType::TYPE_DOCUMENT => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_FLEXPAPER], + SubdefType::TYPE_FLASH => [SubdefSpecs::TYPE_IMAGE], + SubdefType::TYPE_IMAGE => [SubdefSpecs::TYPE_IMAGE], + SubdefType::TYPE_VIDEO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_VIDEO, SubdefSpecs::TYPE_ANIMATION], + SubdefType::TYPE_UNKNOWN => [SubdefSpecs::TYPE_IMAGE], + ]; + const CLASS_THUMBNAIL = 'thumbnail'; + const CLASS_PREVIEW = 'preview'; + const CLASS_DOCUMENT = 'document'; + const DEVICE_ALL = 'all'; + const DEVICE_HANDHELD = 'handheld'; + const DEVICE_PRINT = 'print'; + const DEVICE_PROJECTION = 'projection'; + const DEVICE_SCREEN = 'screen'; + const DEVICE_TV = 'tv'; /** - * @var bool - */ - private $orderable; - - /** + * * @param SubdefType $type * @param SimpleXMLElement $sd - * @param TranslatorInterface $translator + * + * @return databox_subdef */ public function __construct(SubdefType $type, SimpleXMLElement $sd, TranslatorInterface $translator) { $this->subdef_group = $type; - $this->class = (string) $sd->attributes()->class; + $this->class = (string)$sd->attributes()->class; $this->translator = $translator; - foreach ($sd->devices as $device) { - $this->devices[] = (string) $device; + $this->devices[] = (string)$device; } - $this->name = strtolower($sd->attributes()->name); $this->downloadable = p4field::isyes($sd->attributes()->downloadable); $this->orderable = isset($sd->attributes()->orderable) ? p4field::isyes($sd->attributes()->orderable) : true; $this->path = trim($sd->path) !== '' ? p4string::addEndSlash(trim($sd->path)) : ''; - - $this->requiresMetadataUpdate = p4field::isyes((string) $sd->meta); - + $this->preset = $sd->attributes()->presets; + $this->requiresMetadataUpdate = p4field::isyes((string)$sd->meta); foreach ($sd->label as $label) { - $lang = trim((string) $label->attributes()->lang); - + $lang = trim((string)$label->attributes()->lang); if ($lang) { - $this->labels[$lang] = (string) $label; + $this->labels[$lang] = (string)$label; } } - - switch ((string) $sd->mediatype) { + switch ((string)$sd->mediatype) { default: case SubdefSpecs::TYPE_IMAGE: $this->subdef_type = $this->buildImageSubdef($sd); @@ -118,7 +105,6 @@ class databox_subdef break; } } - /** * Build Image Subdef object depending the SimpleXMLElement * @@ -128,7 +114,6 @@ class databox_subdef protected function buildImageSubdef(SimpleXMLElement $sd) { $image = new Image($this->translator); - if ($sd->icodec) { $image->setOptionValue(Image::OPTION_ICODEC, (string) $sd->icodec); } @@ -147,10 +132,8 @@ class databox_subdef if ($sd->flatten) { $image->setOptionValue(Image::OPTION_FLATTEN, p4field::isyes($sd->flatten)); } - return $image; } - /** * Build Audio Subdef object depending the SimpleXMLElement * @@ -160,7 +143,6 @@ class databox_subdef protected function buildAudioSubdef(SimpleXMLElement $sd) { $audio = new Audio($this->translator); - if ($sd->acodec) { $audio->setOptionValue(Audio::OPTION_ACODEC, (string) $sd->acodec); } @@ -170,10 +152,8 @@ class databox_subdef if ($sd->audiosamplerate) { $audio->setOptionValue(Audio::OPTION_AUDIOSAMPLERATE, (int) $sd->audiosamplerate); } - return $audio; } - /** * Build Video Subdef object depending the SimpleXMLElement * @@ -183,7 +163,6 @@ class databox_subdef protected function buildVideoSubdef(SimpleXMLElement $sd) { $video = new Video($this->translator); - if ($sd->size) { $video->setOptionValue(Video::OPTION_SIZE, (int) $sd->size); } @@ -208,10 +187,8 @@ class databox_subdef if ($sd->GOPsize) { $video->setOptionValue(Video::OPTION_GOPSIZE, (int) $sd->GOPsize); } - return $video; } - /** * Build GIF Subdef object depending the SimpleXMLElement * @@ -221,17 +198,14 @@ class databox_subdef protected function buildGifSubdef(SimpleXMLElement $sd) { $gif = new Gif($this->translator); - if ($sd->size) { $gif->setOptionValue(Gif::OPTION_SIZE, (int) $sd->size); } if ($sd->delay) { $gif->setOptionValue(Gif::OPTION_DELAY, (int) $sd->delay); } - return $gif; } - /** * Build Flexpaper Subdef object depending the SimpleXMLElement * @@ -242,8 +216,8 @@ class databox_subdef { return new FlexPaper($this->translator); } - /** + * * @return string */ public function get_class() @@ -252,6 +226,16 @@ class databox_subdef } /** + * + * @return string + */ + public function get_preset() + { + return $this->preset; + } + + /** + * * @return string */ public function get_path() @@ -262,7 +246,7 @@ class databox_subdef /** * The devices matching this subdefinition * - * @return array + * @return Array */ public function getDevices() { @@ -272,7 +256,7 @@ class databox_subdef /** * The current SubdefType the subdef converts documents * - * @return \Alchemy\Phrasea\Media\Subdef\Subdef + * @return Alchemy\Phrasea\Media\Subdef\Subdef */ public function getSubdefType() { @@ -292,7 +276,7 @@ class databox_subdef /** * An associative label ; keys are i18n languages * - * @return array + * @return Array */ public function get_labels() { @@ -306,36 +290,19 @@ class databox_subdef } elseif (isset($this->labels[$code])) { return $this->labels[$code]; } - return null; } /** - * The name of the subdef + * boolean * - * @return string + * @return type */ - public function get_name() - { - return $this->name; - } - - /** - * @return bool - */ - public function isDownloadable() + public function is_downloadable() { return $this->downloadable; } - /** - * @return bool - */ - public function isOrderable() - { - return $this->orderable; - } - /** * Get an array of Alchemy\Phrasea\Media\Subdef\Subdef available for the current Media Type * @@ -344,7 +311,6 @@ class databox_subdef public function getAvailableSubdefTypes() { $subdefTypes = []; - $availableDevices = [ self::DEVICE_ALL, self::DEVICE_HANDHELD, @@ -353,11 +319,8 @@ class databox_subdef self::DEVICE_SCREEN, self::DEVICE_TV, ]; - if (isset(self::$mediaTypeToSubdefTypes[$this->subdef_group->getType()])) { - foreach (self::$mediaTypeToSubdefTypes[$this->subdef_group->getType()] as $subdefType) { - if ($subdefType == $this->subdef_type->getType()) { $mediatype_obj = $this->subdef_type; } else { @@ -385,13 +348,11 @@ class databox_subdef break; } } - - $mediatype_obj->registerOption(new \Alchemy\Phrasea\Media\Subdef\OptionType\Multi($this->translator->trans('Target Device'), 'devices', $availableDevices, $this->devices)); - + $mediatype_obj->registerOption(new \Alchemy\Phrasea\Media\Subdef\OptionType\Multi($this->translator->trans('Target Device'), + 'devices', $availableDevices, $this->devices)); $subdefTypes[] = $mediatype_obj; } } - return $subdefTypes; } @@ -405,6 +366,16 @@ class databox_subdef return $this->requiresMetadataUpdate; } + /** + * The name of the subdef + * + * @return string + */ + public function get_name() + { + return $this->name; + } + /** * Get the MediaAlchemyst specs for the current subdef * @@ -424,4 +395,4 @@ class databox_subdef { return $this->subdef_type->getOptions(); } -} +} \ No newline at end of file diff --git a/lib/classes/databox/subdefsStructure.php b/lib/classes/databox/subdefsStructure.php index 1f856f5bf3..bc84f83051 100644 --- a/lib/classes/databox/subdefsStructure.php +++ b/lib/classes/databox/subdefsStructure.php @@ -9,8 +9,8 @@ */ use Alchemy\Phrasea\Databox\SubdefGroup; -use Alchemy\Phrasea\Media\MediaTypeFactory; use Assert\Assertion; +use Alchemy\Phrasea\Media\MediaTypeFactory; use Symfony\Component\Translation\TranslatorInterface; class databox_subdefsStructure implements IteratorAggregate, Countable @@ -185,15 +185,19 @@ class databox_subdefsStructure implements IteratorAggregate, Countable * @param string $groupname * @param string $name * @param string $class + * @param string $mediatype + * @param string $preset * @return databox_subdefsStructure */ - public function add_subdef($groupname, $name, $class) + public function add_subdef($groupname, $name, $class, $mediatype, $preset) { $dom_struct = $this->databox->get_dom_structure(); $subdef = $dom_struct->createElement('subdef'); $subdef->setAttribute('class', $class); $subdef->setAttribute('name', mb_strtolower($name)); + $subdef->setAttribute('presets', $preset); + $subdef->setAttribute('mediaType', $mediatype); $dom_xp = $this->databox->get_xpath_structure(); $query = '//record/subdefs/subdefgroup[@name="' . $groupname . '"]'; @@ -234,19 +238,18 @@ class databox_subdefsStructure implements IteratorAggregate, Countable } } } - /** * @param string $group * @param string $name * @param string $class + * @param string $preset * @param boolean $downloadable * @param array $options * @param array $labels - * @param bool $orderable * @return databox_subdefsStructure * @throws Exception */ - public function set_subdef($group, $name, $class, $downloadable, $options, $labels, $orderable = true) + public function set_subdef($group, $name, $class, $downloadable, $options, $labels, $preset = "Custom") { $dom_struct = $this->databox->get_dom_structure(); @@ -254,7 +257,7 @@ class databox_subdefsStructure implements IteratorAggregate, Countable $subdef->setAttribute('class', $class); $subdef->setAttribute('name', mb_strtolower($name)); $subdef->setAttribute('downloadable', ($downloadable ? 'true' : 'false')); - $subdef->setAttribute('orderable', ($orderable ? 'true' : 'false')); + $subdef->setAttribute('presets', $preset); foreach ($labels as $code => $label) { $child = $dom_struct->createElement('label'); diff --git a/resources/www/admin/styles/main.scss b/resources/www/admin/styles/main.scss index 0ffe631229..cd9c015d61 100644 --- a/resources/www/admin/styles/main.scss +++ b/resources/www/admin/styles/main.scss @@ -336,6 +336,99 @@ div.switch_right.unchecked { margin-top: 5px; } +.alert .close { + text-decoration: none; +} + +.subdefs [id^="box"] { + display: none; +} + +.subdefs .subviews-submit { + position: fixed; + top: 75px; + right: 40px; + z-index: 1; +} +h2.subdefName { + display: inline-block; + margin-right: 1.5rem; +} + +.reload, .loader, .status { + display: inline-block; +} + +.langTab { + display: inline-block; + vertical-align: top; +} + +.langTab h3{ + font-weight: 700; + font-size: 13px; + margin: 4px 0; + line-height: 11px; + text-align: center; +} + +.toggle{ + display: block; + margin: 15px 0; + color: #08c; + cursor: pointer; +} +.subdefTab input, .langTab input{ + margin: 0; +} + +label[for="elasticsearch_settings_highlight"] { + display: inline-block; + margin-left: 0.5rem; + margin-bottom: 1rem; +} +input[id="elasticsearch_settings_highlight"] { + float: left; +} + +#downbutton { + margin: 1rem 0; +} +#upbutton { + width: 100%; + text-align: left; +} + +#upbutton i { + position: relative; + left: -5px; +} + +#downbutton i { + position: relative; + left: -5px; +} + +.form-horizontal .controls + div { + margin-left: 180px; + font-style: italic; +} + +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + margin-bottom: 7rem; + overflow: visible; +} + +@media screen and (max-width: 1150px) { + .langTab{ + display: block; + } +} + @import './databases'; @import './fields'; -@import './tables'; +@import './tables'; \ No newline at end of file diff --git a/templates/web/admin/subdefs.html.twig b/templates/web/admin/subdefs.html.twig index d2d5080027..6fadce7bdc 100644 --- a/templates/web/admin/subdefs.html.twig +++ b/templates/web/admin/subdefs.html.twig @@ -15,372 +15,564 @@ {# #} - {% endblock %} {% block content %} -

    - -

    - + -
    -

    -
    -
    - -
    - - -
    - -
    +
    +

    +
    +
    + +
    + + + + + + + + +
    + +
    -
    -
    -
      + +
      +
        + {% for subdefgroup, subdeflist in subdefs %} +
      • {{subdefgroup}}
      • + {% endfor %} +
      + {% for subdefgroup, subdeflist in subdefs %} -
    • {{subdefgroup}}
    • - {% endfor %} -
    - - {% for subdefgroup, subdeflist in subdefs %} -
    -
    -
  • + {% set useTruncation = app['settings'].getUserSetting(app.getAuthenticatedUser(), 'use_truncation') %} +
    Date: Mon, 20 Nov 2017 12:16:54 +0400 Subject: [PATCH 02/25] Show all available structure for install CLI/Graphic mode --- cache/.gitkeep | 0 lib/Alchemy/Phrasea/Command/Setup/Install.php | 6 +- .../Phrasea/Controller/SetupController.php | 2 +- .../Core/Configuration/StructureTemplate.php | 93 +++++++++++++++++++ .../Provider/ConfigurationServiceProvider.php | 6 ++ lib/Alchemy/Phrasea/Setup/Installer.php | 2 +- templates/web/setup/step2.html.twig | 4 +- 7 files changed, 107 insertions(+), 6 deletions(-) delete mode 100644 cache/.gitkeep create mode 100644 lib/Alchemy/Phrasea/Core/Configuration/StructureTemplate.php diff --git a/cache/.gitkeep b/cache/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/Alchemy/Phrasea/Command/Setup/Install.php b/lib/Alchemy/Phrasea/Command/Setup/Install.php index f5a7ccf817..071baf5bb2 100644 --- a/lib/Alchemy/Phrasea/Command/Setup/Install.php +++ b/lib/Alchemy/Phrasea/Command/Setup/Install.php @@ -176,6 +176,7 @@ class Install extends Command private function getDBConn(InputInterface $input, OutputInterface $output, Connection $abConn, DialogHelper $dialog) { $dbConn = $template = $info = null; + $templates = $this->container['phraseanet.structure-template']->getAvailable(); if (!$input->getOption('databox')) { do { $retry = false; @@ -196,8 +197,9 @@ class Install extends Command $output->writeln("\n\tData-Box : Connection successful !\n"); do { - $template = $dialog->ask($output, 'Choose a language template for metadata structure, available are fr (french) and en (english) (en) : ', 'en'); - } while (!in_array($template, ['en', 'fr'])); + $template = $dialog->ask($output, "Choose a language template for metadata structure, available are {$templates->__toString()} : ", 'en'); + } + while (!in_array($template, array_keys($templates->getTemplates()))); $output->writeln("\n\tLanguage selected is '$template'\n"); } catch (\Exception $e) { diff --git a/lib/Alchemy/Phrasea/Controller/SetupController.php b/lib/Alchemy/Phrasea/Controller/SetupController.php index b18dd7965b..36eaaae141 100644 --- a/lib/Alchemy/Phrasea/Controller/SetupController.php +++ b/lib/Alchemy/Phrasea/Controller/SetupController.php @@ -77,7 +77,7 @@ class SetupController extends Controller return $this->render('/setup/step2.html.twig', [ 'locale' => $this->app['locale'], 'available_locales' => Application::getAvailableLanguages(), - 'available_templates' => ['en', 'fr'], + 'available_templates' => $this->app['phraseanet.structure-template']->getAvailable()->getTemplates(), 'warnings' => $warnings, 'error' => $request->query->get('error'), 'current_servername' => $request->getScheme() . '://' . $request->getHttpHost() . '/', diff --git a/lib/Alchemy/Phrasea/Core/Configuration/StructureTemplate.php b/lib/Alchemy/Phrasea/Core/Configuration/StructureTemplate.php new file mode 100644 index 0000000000..727cdd0bce --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Configuration/StructureTemplate.php @@ -0,0 +1,93 @@ +app = $app; + } + /** + * @return $this + * @throws \Exception + */ + public function getAvailable() + { + $templateList = new \DirectoryIterator($this->app['root.path'] . '/lib/conf.d/data_templates'); + if(empty($templateList)) throw new \Exception('No available structure template'); + $templates = []; + $abbreviationLength = 2; + foreach ($templateList as $template) + { + if($template->isDot() + || !$template->isFile() + || $template->getExtension() !== self::TEMPLATE_EXTENSION) continue; + $name = $template->getFilename(); + $abbreviation = strtolower(substr($name,0,$abbreviationLength)); + if(array_key_exists($abbreviation,$templates) ){ + $abbreviation = strtolower(substr($name,0,++$abbreviationLength)); + } + $templates[$abbreviation] = $template->getBasename('.'.self::TEMPLATE_EXTENSION); + } + $this->templates = $templates; + return $this; + } + /** + * @return string + */ + public function __toString() + { + if(!$this->templates){ + return ''; + } + $templateToString = ''; + $cpt = 1; + $templateLength = count($this->templates); + foreach ($this->templates as $key => $value){ + if (($templateLength - 1) == $cpt) { + $separator = ' and '; + }elseif(end($this->templates) == $value){ + $separator = ''; + }else{ + $separator = ', '; + } + $templateToString .= $key.' ('.$value.')'. $separator; + $cpt++; + } + return $templateToString; + } + /** + * @param $template + * @return mixed + * @throws \Exception + */ + public function getTemplateName($template = 'en'){ + if(!array_key_exists($template,$this->templates)){ + throw new \Exception('Not found template : '.$template); + } + return $this->templates[$template]; + } + /** + * @return mixed + */ + public function getTemplates() + { + return $this->templates; + } +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Core/Provider/ConfigurationServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/ConfigurationServiceProvider.php index 55623e0081..c7cec0227e 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/ConfigurationServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/ConfigurationServiceProvider.php @@ -11,6 +11,8 @@ namespace Alchemy\Phrasea\Core\Provider; +use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Core\Configuration\StructureTemplate; use Alchemy\Phrasea\Core\Configuration\AccessRestriction; use Alchemy\Phrasea\Core\Configuration\Configuration; use Alchemy\Phrasea\Core\Configuration\DisplaySettingService; @@ -71,6 +73,10 @@ class ConfigurationServiceProvider implements ServiceProviderInterface $app['conf.restrictions'] = $app->share(function (SilexApplication $app) { return new AccessRestriction($app['conf'], $app->getApplicationBox(), $app['monolog']); }); + + $app['phraseanet.structure-template'] = $app->share(function (Application $app) { + return new StructureTemplate($app); + }); } /** diff --git a/lib/Alchemy/Phrasea/Setup/Installer.php b/lib/Alchemy/Phrasea/Setup/Installer.php index 2868f79835..0700eb1907 100644 --- a/lib/Alchemy/Phrasea/Setup/Installer.php +++ b/lib/Alchemy/Phrasea/Setup/Installer.php @@ -53,7 +53,7 @@ class Installer private function createDB(Connection $dbConn = null, $template, User $admin) { - $template = new \SplFileInfo(__DIR__ . '/../../../conf.d/data_templates/' . $template . '-simple.xml'); + $template = new \SplFileInfo(__DIR__ . '/../../../conf.d/data_templates/' . $this->app['phraseanet.structure-template']->getAvailable()->getTemplateName($template) . '.xml'); $databox = \databox::create($this->app, $dbConn, $template); $this->app->getAclForUser($admin) diff --git a/templates/web/setup/step2.html.twig b/templates/web/setup/step2.html.twig index 3984f7fd27..83f3329ef8 100644 --- a/templates/web/setup/step2.html.twig +++ b/templates/web/setup/step2.html.twig @@ -738,8 +738,8 @@
    - - - - - - - - - - - - -
    -

    {{ 'subdef.document' | trans }}

    -
    {{ 'subdef.orderable' | trans }}
    - - {% for subdefname , subdef in subdeflist %} -
    - - - - - - - - - - {% for code, language in app['locales.available'] %} +
    +
    +
    -

    {{subdefname}}

    - -
    + - - + + - {% endfor %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {{ language }} +

    {{ 'subdef.document' | trans }}

    +
    {{ 'Telechargeable' | trans }}
    {{ 'subdef.orderable' | trans }}
    - {{ 'classe' | trans }} - - -
    - Path - - -
    - {{ 'Write Metas' | trans }} - - -
    - {{ 'mediatype' | trans }} - - -
    - {% for subdefType in subdef.getAvailableSubdefTypes() %} -
    - - {% for option in subdefType.getOptions() %} - {% set varname = subdefgroup~'_'~subdefname~'_'~subdefType.getType()~'['~ option.getName() ~']' %} - - - + + {% endfor %} - - {% elseif option.getType() == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_BOOLEAN') %} - {{ 'yes' | trans }} - {{ 'no' | trans }} - {% elseif option.getType() == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_MULTI') %} - {% for pot_value, selected in option.Value(true) %} - - {% endfor %} - {% endif %} - - - +
    - {{option.getDisplayName()}} - - {% set extradata = '' %} - {% if option.getType() == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_RANGE') %} -
    - - {% elseif option.getType() == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_ENUM') %} - + + {% for pot_value in option.getAvailableValues() %} + + {% endfor %} + + {% elseif option.getType() == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_BOOLEAN') %} + {{ 'yes' | trans }} + {{ 'no' | trans }} + {% elseif option.getType() == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_MULTI') %} + {% for pot_value, selected in option.Value(true) %} + + {% endfor %} + {% endif %} +
    + {% if option.type == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_RANGE') %} + + {% endif %} +
    - {% if option.type == constant('\\Alchemy\\Phrasea\\Media\\Subdef\\OptionType\\OptionType::TYPE_RANGE') %} - - {% endif %} -
    +
    + {% endfor %} +
    + {% endfor %} - - {% endfor %} - {% endfor %} - {% endfor %} - - - - - -
    - -
    - + + + + + + + -
    -
    +
    +
    +
    -
    {% endblock %} diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php index 2aced1154a..4d413c2e9d 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php @@ -3,7 +3,6 @@ namespace Alchemy\Tests\Phrasea\Controller\Admin; use Alchemy\Phrasea\Media\Subdef\Image; - /** * @group functional * @group legacy @@ -13,9 +12,7 @@ use Alchemy\Phrasea\Media\Subdef\Image; class SubdefsTest extends \PhraseanetAuthenticatedWebTestCase { protected $client; - protected $databox_id; - public function setUp() { parent::setUp(); @@ -24,12 +21,10 @@ class SubdefsTest extends \PhraseanetAuthenticatedWebTestCase $databox = array_shift($databoxes); $this->databox_id = $databox->get_sbas_id(); } - public function getSubdefName() { return 'testname' . time() . mt_rand(10000, 99999); } - /** * Default route test */ @@ -38,73 +33,63 @@ class SubdefsTest extends \PhraseanetAuthenticatedWebTestCase self::$DI['client']->request("GET", "/admin/subdefs/" . $this->databox_id . "/"); $this->assertTrue(self::$DI['client']->getResponse()->isOk()); } - public function testPostRouteAddSubdef() { $name = $this->getSubdefName(); self::$DI['client']->request("POST", "/admin/subdefs/" . $this->databox_id . "/", ['add_subdef' => [ - 'class' => 'thumbnail', - 'name' => $name, - 'group' => 'image' - ]]); + 'class' => 'thumbnail', + 'name' => $name, + 'group' => 'image' + ]]); $this->assertTrue(self::$DI['client']->getResponse()->isRedirect()); - $app = $this->getApplication(); $subdefs = new \databox_subdefsStructure($app->findDataboxById($this->databox_id), $app['translator']); $subdefs->delete_subdef('image', $name); } - public function testPostRouteDeleteSubdef() { $subdefs = $this->getApplication()->findDataboxById($this->databox_id)->get_subdef_structure(); $name = $this->getSubdefName(); - $subdefs->add_subdef("image", $name, "thumbnail"); + $subdefs->add_subdef("image", $name, "thumbnail", "image", "1280px JPG (preview Phraseanet)"); self::$DI['client']->request("POST", "/admin/subdefs/" . $this->databox_id . "/", ['delete_subdef' => 'image_' . $name]); $this->assertTrue(self::$DI['client']->getResponse()->isRedirect()); try { $subdefs->get_subdef("image", $name); $this->fail("should raise an exception"); } catch (\Exception $e) { - } } - public function testPostRouteAddSubdefWithNoParams() { $subdefs = $this->getApplication()->findDataboxById($this->databox_id)->get_subdef_structure(); $name = $this->getSubdefName(); - $subdefs->add_subdef("image", $name, "thumbnail"); + $subdefs->add_subdef("image", $name, "thumbnail", "image", "1280px JPG (preview Phraseanet)"); self::$DI['client']->request("POST", "/admin/subdefs/" . $this->databox_id . "/" , ['subdefs' => [ 'image_' . $name ] - , 'image_' . $name . '_class' => 'thumbnail' - , 'image_' . $name . '_downloadable' => 0 - , 'image_' . $name . '_mediatype' => 'image' - , 'image_' . $name . '_image' => [ - 'size' => 400, - 'resolution' => 83, - 'strip' => 0, - 'quality' => 90, - ]] + , 'image_' . $name . '_class' => 'thumbnail' + , 'image_' . $name . '_downloadable' => 0 + , 'image_' . $name . '_mediatype' => 'image' + , 'image_' . $name . '_image' => [ + 'size' => 400, + 'resolution' => 83, + 'strip' => 0, + 'quality' => 90, + ]] ); - $this->assertTrue(self::$DI['client']->getResponse()->isRedirect()); $app = $this->getApplication(); $subdefs = new \databox_subdefsStructure($app->findDataboxById($this->databox_id), $app['translator']); $subdef = $subdefs->get_subdef("image", $name); - - $this->assertFalse($subdef->isDownloadable()); - + /* @var $subdef \databox_subdef */ + $this->assertFalse($subdef->is_downloadable()); $options = $subdef->getOptions(); - $this->assertTrue(is_array($options)); - $this->assertEquals(400, $options[Image::OPTION_SIZE]->getValue()); $this->assertEquals(83, $options[Image::OPTION_RESOLUTION]->getValue()); $this->assertEquals(90, $options[Image::OPTION_QUALITY]->getValue()); $this->assertFalse($options[Image::OPTION_STRIP]->getValue()); - $subdefs->delete_subdef("image", $name); } -} +} \ No newline at end of file From e9e9a737c39e6e04b47a1c515c35404721830ed1 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Wed, 13 Dec 2017 10:26:24 +0400 Subject: [PATCH 10/25] PORT PHRAS-1559 and PHRAS-1560 to 4.1 --- .../Prod/MoveCollectionController.php | 25 ++++++++++ .../Controller/Prod/UploadController.php | 47 ++++++++++++++----- .../Configuration/DisplaySettingService.php | 5 ++ lib/Alchemy/Phrasea/Helper/Prod.php | 26 +++++++++- templates/web/prod/index.html.twig | 13 +++++ 5 files changed, 104 insertions(+), 12 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php b/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php index e838b61d5f..d89fc9ae32 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/MoveCollectionController.php @@ -36,6 +36,31 @@ class MoveCollectionController extends Controller } else { // is able to move: $success = true; + + /** @var DisplaySettingService $settings */ + $settings = $this->app['settings']; + $userOrderSetting = $settings->getUserSetting($this->app->getAuthenticatedUser(), 'order_collection_by'); + // a temporary array to sort the collections + $aName = array(); + list($ukey, $uorder) = ["order", SORT_ASC]; // default ORDER_BY_ADMIN + switch ($userOrderSetting) { + case $settings::ORDER_ALPHA_ASC : + list($ukey, $uorder) = ["name", SORT_ASC]; + break; + case $settings::ORDER_ALPHA_DESC : + list($ukey, $uorder) = ["name", SORT_DESC]; + break; + } + foreach ($collections as $key => $row) { + if($ukey == "order") { + $aName[$key] = $row->get_ord(); + }else { + $aName[$key] = $row->get_name(); + } + } + // sort the collections + array_multisort($aName, $uorder, SORT_REGULAR, $collections); + $parameters = [ 'records' => $records, 'message' => '', diff --git a/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php b/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php index 846b934fd7..85bd81def4 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/UploadController.php @@ -243,20 +243,45 @@ class UploadController extends Controller { $collections = []; - foreach ($acl->get_granted_base([\ACL::CANADDRECORD]) as $collection) { - $databox = $collection->get_databox(); - - if ( ! isset($collections[$databox->get_sbas_id()])) { - $collections[$databox->get_sbas_id()] = [ - 'databox' => $databox, - 'databox_collections' => [] - ]; + foreach ($acl->get_granted_sbas() as $databox) { + $sbasId = $databox->get_sbas_id(); + foreach ($acl->get_granted_base([\ACL::CANADDRECORD], [$sbasId]) as $collection) { + $databox = $collection->get_databox(); + if ( ! isset($collections[$sbasId])) { + $collections[$databox->get_sbas_id()] = [ + 'databox' => $databox, + 'databox_collections' => [] + ]; + } + $collections[$databox->get_sbas_id()]['databox_collections'][] = $collection; + /** @var DisplaySettingService $settings */ + $settings = $this->app['settings']; + $userOrderSetting = $settings->getUserSetting($this->app->getAuthenticatedUser(), 'order_collection_by'); + // a temporary array to sort the collections + $aName = []; + list($ukey, $uorder) = ["order", SORT_ASC]; // default ORDER_BY_ADMIN + switch ($userOrderSetting) { + case $settings::ORDER_ALPHA_ASC : + list($ukey, $uorder) = ["name", SORT_ASC]; + break; + case $settings::ORDER_ALPHA_DESC : + list($ukey, $uorder) = ["name", SORT_DESC]; + break; + } + foreach ($collections[$databox->get_sbas_id()]['databox_collections'] as $key => $row) { + if ($ukey == "order") { + $aName[$key] = $row->get_ord(); + } + else { + $aName[$key] = $row->get_name(); + } + } + // sort the collections + array_multisort($aName, $uorder, SORT_REGULAR, $collections[$databox->get_sbas_id()]['databox_collections']); } - - $collections[$databox->get_sbas_id()]['databox_collections'][] = $collection; } - return $collections; + } /** diff --git a/lib/Alchemy/Phrasea/Core/Configuration/DisplaySettingService.php b/lib/Alchemy/Phrasea/Core/Configuration/DisplaySettingService.php index b82b3501e0..532c8cf247 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/DisplaySettingService.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/DisplaySettingService.php @@ -15,6 +15,10 @@ use Alchemy\Phrasea\Model\Entities\User; class DisplaySettingService { + const ORDER_ALPHA_ASC = "ORDER_ALPHA_ASC"; + const ORDER_ALPHA_DESC = "ORDER_ALPHA_DESC"; + const ORDER_BY_ADMIN = "ORDER_BY_ADMIN"; + /** * The default user settings. * @@ -34,6 +38,7 @@ class DisplaySettingService 'client_basket_status' => '1', 'css' => '000000', 'start_page_query' => '', + 'order_collection_by' => self::ORDER_BY_ADMIN, 'start_page' => 'QUERY', 'rollover_thumbnail' => 'caption', 'technical_display' => '1', diff --git a/lib/Alchemy/Phrasea/Helper/Prod.php b/lib/Alchemy/Phrasea/Helper/Prod.php index 3537b367c0..54470f60ee 100644 --- a/lib/Alchemy/Phrasea/Helper/Prod.php +++ b/lib/Alchemy/Phrasea/Helper/Prod.php @@ -46,10 +46,34 @@ class Prod extends Helper $selected = $saveSettings ? ((isset($searchSet['bases']) && isset($searchSet['bases'][$sbasId])) ? (in_array($coll->get_base_id(), $searchSet['bases'][$sbasId])) : true) : true; $bases[$sbasId]['collections'][] = array( 'selected' => $selected, - 'base_id' => $coll->get_base_id() + 'base_id' => $coll->get_base_id(), + 'name' => $coll->get_name(), + 'order' => $coll->get_ord() ); } + /** @var DisplaySettingService $settings */ + $settings = $this->app['settings']; + $userOrderSetting = $settings->getUserSetting($this->app->getAuthenticatedUser(), 'order_collection_by'); + + // a temporary array to sort the collections + $aName = array(); + list($ukey, $uorder) = ["order", SORT_ASC]; // default ORDER_BY_ADMIN + switch ($userOrderSetting) { + case $settings::ORDER_ALPHA_ASC : + list($ukey, $uorder) = ["name", SORT_ASC]; + break; + + case $settings::ORDER_ALPHA_DESC : + list($ukey, $uorder) = ["name", SORT_DESC]; + break; + } + foreach ($bases[$sbasId]['collections'] as $key => $row) { + $aName[$key] = $row[$ukey]; + } + // sort the collections + array_multisort($aName, $uorder, SORT_REGULAR, $bases[$sbasId]['collections']); + foreach ($databox->get_meta_structure() as $fieldMeta) { if (!$fieldMeta->is_indexable()) { continue; diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig index 6e8d7118d6..b5252c37f9 100644 --- a/templates/web/prod/index.html.twig +++ b/templates/web/prod/index.html.twig @@ -664,6 +664,19 @@
    +
    +

    {{ 'Collection order' | trans }}

    +
    + {% set order_collection_by = app['settings'].getUserSetting(app.getAuthenticatedUser(), 'order_collection_by') %} + +
    +

    {{ 'index::advance_search: facet' | trans }}

    {% set facetFilter = app['settings'].getUserSetting(app.getAuthenticatedUser(), 'facet') %} From 2811964f01c24e81943fa699c8c397b22064f73d Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Wed, 13 Dec 2017 12:51:08 +0400 Subject: [PATCH 11/25] PORT PHRAS-1301/PHRAS-1676 to 4.1 --- templates/web/prod/upload/upload-flash.html.twig | 5 +++-- templates/web/prod/upload/upload.html.twig | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/templates/web/prod/upload/upload-flash.html.twig b/templates/web/prod/upload/upload-flash.html.twig index c0d801df55..f912f72a64 100644 --- a/templates/web/prod/upload/upload-flash.html.twig +++ b/templates/web/prod/upload/upload-flash.html.twig @@ -54,11 +54,12 @@
    {{ 'upload:: Destination (collection) :' | trans }} :
    {# collections list #} {% if collections|length > 0 %} - {% for sbasId, availableCollections in collections %} {% for collection in availableCollections['databox_collections'] %} - + {% endfor %} {% endfor %} diff --git a/templates/web/prod/upload/upload.html.twig b/templates/web/prod/upload/upload.html.twig index 1e5d5a1565..325b58b101 100644 --- a/templates/web/prod/upload/upload.html.twig +++ b/templates/web/prod/upload/upload.html.twig @@ -55,14 +55,15 @@
    {{ 'upload:: Destination (collection) :' | trans }} :
    {# collections list #} - + {% for sbasId, availableCollections in collections %} + + {% for collection in availableCollections['databox_collections'] %} + + {% endfor %} + {% endfor %} - - {% endfor %} {# collections status #} {% for availableCollections in collections %} From d0a1c4c599cfa6fc322c891122d332802c1f54d7 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Thu, 14 Dec 2017 11:32:08 +0400 Subject: [PATCH 12/25] PORT PHRAS-1614 to 4.1 --- templates/web/prod/index.html.twig | 36 +++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig index 6e8d7118d6..eb57320317 100644 --- a/templates/web/prod/index.html.twig +++ b/templates/web/prod/index.html.twig @@ -200,39 +200,53 @@
  • {% if app['conf'].get(['registry', 'modules', 'stories']) and app.getAclForUser(app.getAuthenticatedUser()).has_right(constant('\\ACL::CANADDRECORD')) %} -
  • - - {{ 'phraseanet:: tri par date' | trans }} + + + {{ 'phraseanet:: tri par date' | trans }} +
  • - - {{ 'phraseanet:: tri par nom' | trans }} + + + {{ 'phraseanet:: tri par nom' | trans }} +
  • - {{ 'Preferences' | trans }} + + {{ 'Preferences' | trans }} +
  • From d49ef51a9aae472dbe09e6582403b20845d2ff7a Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Thu, 14 Dec 2017 11:32:30 +0400 Subject: [PATCH 13/25] add images --- .../www/common/images/icons/browse_basket.png | Bin 0 -> 995 bytes .../common/images/icons/icon_collection_bin.png | Bin 0 -> 2275 bytes .../www/common/images/icons/icon_empty_bin.png | Bin 0 -> 4009 bytes resources/www/common/images/icons/new_basket.png | Bin 0 -> 2260 bytes resources/www/common/images/icons/new_report.png | Bin 0 -> 1824 bytes resources/www/common/images/icons/sort_alpha.png | Bin 0 -> 552 bytes resources/www/common/images/icons/sort_date.png | Bin 0 -> 321 bytes 7 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/www/common/images/icons/browse_basket.png create mode 100644 resources/www/common/images/icons/icon_collection_bin.png create mode 100644 resources/www/common/images/icons/icon_empty_bin.png create mode 100644 resources/www/common/images/icons/new_basket.png create mode 100644 resources/www/common/images/icons/new_report.png create mode 100644 resources/www/common/images/icons/sort_alpha.png create mode 100644 resources/www/common/images/icons/sort_date.png diff --git a/resources/www/common/images/icons/browse_basket.png b/resources/www/common/images/icons/browse_basket.png new file mode 100644 index 0000000000000000000000000000000000000000..585684376effb90c57422ef4d208e31dff0c4ef5 GIT binary patch literal 995 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 literal 0 HcmV?d00001 diff --git a/resources/www/common/images/icons/icon_empty_bin.png b/resources/www/common/images/icons/icon_empty_bin.png new file mode 100644 index 0000000000000000000000000000000000000000..240aa01118c175caf68a5b818451cd187833a586 GIT binary patch literal 4009 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 P00000NkvXXu0mjffAgZ_ literal 0 HcmV?d00001 diff --git a/resources/www/common/images/icons/new_basket.png b/resources/www/common/images/icons/new_basket.png new file mode 100644 index 0000000000000000000000000000000000000000..a85a564919abcc94f51fdda7662343d0720f462e GIT binary patch literal 2260 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 TfuK1B00000NkvXXu0mjfr~Qlf literal 0 HcmV?d00001 From 0d7c2bd52d8e95672435d8cc0c452a633d72ca5c Mon Sep 17 00:00:00 2001 From: jygaulier Date: Thu, 14 Dec 2017 11:15:07 +0100 Subject: [PATCH 14/25] PHRAS-1760_Provisionning-error_Master (#2396) fix mismatch "database" (bad) -> "appbox_db" (good) variable in ansible scripts --- resources/ansible/roles/app/templates/configuration.tpl | 2 +- resources/ansible/roles/mariadb/tasks/main.yml | 2 +- resources/ansible/vars/all.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/ansible/roles/app/templates/configuration.tpl b/resources/ansible/roles/app/templates/configuration.tpl index 346f11020b..bf39dd9a68 100644 --- a/resources/ansible/roles/app/templates/configuration.tpl +++ b/resources/ansible/roles/app/templates/configuration.tpl @@ -12,7 +12,7 @@ main: port: 3306 user: '{{ mariadb.user }}' password: '{{ mariadb.password }}' - dbname: '{{ mariadb.database }}' + dbname: '{{ mariadb.appbox_db }}' driver: pdo_mysql charset: UTF8 database-test: diff --git a/resources/ansible/roles/mariadb/tasks/main.yml b/resources/ansible/roles/mariadb/tasks/main.yml index 6e87843ac9..0fbc016ca1 100644 --- a/resources/ansible/roles/mariadb/tasks/main.yml +++ b/resources/ansible/roles/mariadb/tasks/main.yml @@ -47,7 +47,7 @@ - "{{ mariadb.alt_databox_db }}" - name: mariadb | Import dump - mysql_db: name={{ mariadb.database }} state=import login_user=root login_password={{ mariadb.root_password }} target=/vagrant/{{ mariadb.dump }} + mysql_db: name={{ mariadb.appbox_db }} state=import login_user=root login_password={{ mariadb.root_password }} target=/vagrant/{{ mariadb.dump }} when: mariadb.dump - name: mariadb | Create users diff --git a/resources/ansible/vars/all.yml b/resources/ansible/vars/all.yml index 1475cc804d..26f2941820 100644 --- a/resources/ansible/vars/all.yml +++ b/resources/ansible/vars/all.yml @@ -41,7 +41,7 @@ nginx: mariadb: install: '1' root_password: toor - database: ab_master + appbox_db: ab_master databox_db: db_master alt_databox_db: db_alt user: phraseanet From 3a6f2eb36566c9ff567f23bba2f28074514cf078 Mon Sep 17 00:00:00 2001 From: Xavier Rousset Date: Wed, 13 Dec 2017 19:14:47 +0100 Subject: [PATCH 15/25] Fix travis tests --- lib/classes/databox/subdef.php | 12 ++++++++++-- templates/web/admin/subdefs.html.twig | 2 +- .../Tests/Phrasea/Controller/Admin/SubdefsTest.php | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/classes/databox/subdef.php b/lib/classes/databox/subdef.php index 885685ef89..188e1ccc22 100644 --- a/lib/classes/databox/subdef.php +++ b/lib/classes/databox/subdef.php @@ -296,13 +296,21 @@ class databox_subdef /** * boolean * - * @return type + * @return bool */ - public function is_downloadable() + public function isDownloadable() { return $this->downloadable; } + /** + * @return bool + */ + public function isOrderable() + { + return $this->orderable; + } + /** * Get an array of Alchemy\Phrasea\Media\Subdef\Subdef available for the current Media Type * diff --git a/templates/web/admin/subdefs.html.twig b/templates/web/admin/subdefs.html.twig index 6fadce7bdc..ae3ba4b722 100644 --- a/templates/web/admin/subdefs.html.twig +++ b/templates/web/admin/subdefs.html.twig @@ -401,7 +401,7 @@ {{ 'Telechargeable' | trans }} - + diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php index 4d413c2e9d..54bf3e89b1 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Admin/SubdefsTest.php @@ -83,7 +83,7 @@ class SubdefsTest extends \PhraseanetAuthenticatedWebTestCase $subdefs = new \databox_subdefsStructure($app->findDataboxById($this->databox_id), $app['translator']); $subdef = $subdefs->get_subdef("image", $name); /* @var $subdef \databox_subdef */ - $this->assertFalse($subdef->is_downloadable()); + $this->assertFalse($subdef->isDownloadable()); $options = $subdef->getOptions(); $this->assertTrue(is_array($options)); $this->assertEquals(400, $options[Image::OPTION_SIZE]->getValue()); From c7f6b325d80e6c090bca382b9832a7bef03fc6da Mon Sep 17 00:00:00 2001 From: Xavier Rousset Date: Mon, 18 Dec 2017 18:02:48 +0100 Subject: [PATCH 16/25] PHRAS-1766 Add orderable checkbox for each subdef - Remove order option on groups --- .../Controller/Admin/SubdefsController.php | 34 ++----------------- lib/classes/databox/subdefsStructure.php | 24 +++---------- templates/web/admin/subdefs.html.twig | 23 +++---------- 3 files changed, 11 insertions(+), 70 deletions(-) diff --git a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php index c68c90922f..cdee52835e 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php @@ -149,12 +149,11 @@ class SubdefsController extends Controller break; } - $subdefs->set_subdef($group, $name, $class, false, $options, [], $preset); + $subdefs->set_subdef($group, $name, $class, false, $options, [], true, $preset); } } else { $subdefs = $databox->get_subdef_structure(); - $this->updateSubdefGroups($subdefs, $request); foreach ($Parmsubdefs as $post_sub) { $options = []; @@ -193,7 +192,7 @@ class SubdefsController extends Controller } $labels = $request->request->get($post_sub . '_label', []); - $subdefs->set_subdef($group, $name, $class, $downloadable, $options, $labels, $preset, $orderable); + $subdefs->set_subdef($group, $name, $class, $downloadable, $options, $labels, $orderable, $preset); } } @@ -218,35 +217,6 @@ class SubdefsController extends Controller return $mapping; } - /** - * Update Databox subdefsStructure DOM according to defined groups. - * - * @param \databox_subdefsStructure $subdefs - * @param Request $request - */ - protected function updateSubdefGroups(\databox_subdefsStructure $subdefs, Request $request) - { - $subdefsGroups = $request->request->get('subdefsgroups', []); - $changedGroups = []; - /** @var SubdefGroup $subdefsGroup */ - foreach ($subdefs as $groupName => $subdefsGroup) { - $documentOrderable = isset($subdefsGroups[$groupName]['document_orderable']) - ? \p4field::isyes($subdefsGroups[$groupName]['document_orderable']) - : false; - if ($subdefsGroup->isDocumentOrderable() !== $documentOrderable) { - if ($documentOrderable) { - $subdefsGroup->allowDocumentOrdering(); - } else { - $subdefsGroup->disallowDocumentOrdering(); - } - $changedGroups[] = $subdefsGroup; - } - } - if ($changedGroups) { - $subdefs->updateSubdefGroups($changedGroups); - } - } - /** * @return array */ diff --git a/lib/classes/databox/subdefsStructure.php b/lib/classes/databox/subdefsStructure.php index bc84f83051..9afd912e36 100644 --- a/lib/classes/databox/subdefsStructure.php +++ b/lib/classes/databox/subdefsStructure.php @@ -220,36 +220,19 @@ class databox_subdefsStructure implements IteratorAggregate, Countable return $this; } - /** - * @param SubdefGroup[] $groups - */ - public function updateSubdefGroups($groups) - { - Assertion::allIsInstanceOf($groups, SubdefGroup::class); - - $dom_xp = $this->databox->get_xpath_structure(); - - foreach ($groups as $group) { - $nodes = $dom_xp->query('//record/subdefs/subdefgroup[@name="' . $group->getName() . '"]'); - - /** @var DOMElement $node */ - foreach ($nodes as $node) { - $node->setAttribute('document_orderable', ($group->isDocumentOrderable() ? 'true' : 'false')); - } - } - } /** * @param string $group * @param string $name * @param string $class - * @param string $preset * @param boolean $downloadable * @param array $options * @param array $labels + * @param boolean $orderable + * @param string $preset * @return databox_subdefsStructure * @throws Exception */ - public function set_subdef($group, $name, $class, $downloadable, $options, $labels, $preset = "Custom") + public function set_subdef($group, $name, $class, $downloadable, $options, $labels, $orderable = true, $preset = "Custom") { $dom_struct = $this->databox->get_dom_structure(); @@ -257,6 +240,7 @@ class databox_subdefsStructure implements IteratorAggregate, Countable $subdef->setAttribute('class', $class); $subdef->setAttribute('name', mb_strtolower($name)); $subdef->setAttribute('downloadable', ($downloadable ? 'true' : 'false')); + $subdef->setAttribute('orderable', ($orderable ? 'true' : 'false')); $subdef->setAttribute('presets', $preset); foreach ($labels as $code => $label) { diff --git a/templates/web/admin/subdefs.html.twig b/templates/web/admin/subdefs.html.twig index ae3ba4b722..d103d7022c 100644 --- a/templates/web/admin/subdefs.html.twig +++ b/templates/web/admin/subdefs.html.twig @@ -373,24 +373,6 @@ {% for subdefgroup, subdeflist in subdefs %}
    -
    - - - - - - - - - - - - - -
    -

    {{ 'subdef.document' | trans }}

    -
    {{ 'subdef.orderable' | trans }}
    -
    {% for subdefname , subdef in subdeflist %}
    @@ -404,6 +386,11 @@ + + {{ 'subdef.orderable' | trans }} + + + {{ 'classe' | trans }} From 9c3f65f3f7f92362f0596c990aa38eccbb39e407 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Thu, 21 Dec 2017 16:50:21 +0400 Subject: [PATCH 17/25] load appropriate status based on store collection --- templates/web/prod/upload/upload-flash.html.twig | 2 +- templates/web/prod/upload/upload.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/web/prod/upload/upload-flash.html.twig b/templates/web/prod/upload/upload-flash.html.twig index f912f72a64..f59d0ffadb 100644 --- a/templates/web/prod/upload/upload-flash.html.twig +++ b/templates/web/prod/upload/upload-flash.html.twig @@ -67,7 +67,7 @@ {# collections status #} {% for availableCollections in collections %} {% for collection in availableCollections['databox_collections'] %} -
    +
    {{ 'upload:: Status :' | trans }} :
    diff --git a/templates/web/prod/upload/upload.html.twig b/templates/web/prod/upload/upload.html.twig index 325b58b101..8a23c0d233 100644 --- a/templates/web/prod/upload/upload.html.twig +++ b/templates/web/prod/upload/upload.html.twig @@ -68,7 +68,7 @@ {# collections status #} {% for availableCollections in collections %} {% for collection in availableCollections['databox_collections'] %} -
    +
    {{ 'upload:: Status :' | trans }} :
    From 53b8ca40872a04579822b23e2b51b43b30cc652f Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Fri, 22 Dec 2017 11:15:17 +0400 Subject: [PATCH 18/25] Porting PHRAS-1586/PHRAS-1602 to 4.1 --- resources/www/account/images/favicon.ico | Bin 0 -> 198 bytes templates/web/account/base.html.twig | 4 ++++ www/favicon.ico | Bin 1406 -> 4286 bytes 3 files changed, 4 insertions(+) create mode 100644 resources/www/account/images/favicon.ico diff --git a/resources/www/account/images/favicon.ico b/resources/www/account/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9d0de806a9767fd4b2648ff46231a7a70147a098 GIT binary patch literal 198 zcmZQzU<5(|0VXiLfq{WR42U&=SOAC>fEXkX0uDed#0|krKsE?FANvg?85sWmXJGha LPaX#8r4#@FTmTsV literal 0 HcmV?d00001 diff --git a/templates/web/account/base.html.twig b/templates/web/account/base.html.twig index c6f2213f57..f1574dcbdb 100644 --- a/templates/web/account/base.html.twig +++ b/templates/web/account/base.html.twig @@ -3,6 +3,10 @@ {% extends "common/index_bootstrap.html.twig" %} +{% block icon %} + +{% endblock %} + {% block stylesheet %}