diff --git a/Dockerfile b/Dockerfile index 7ff718ab2c..c40dfc4347 100644 --- a/Dockerfile +++ b/Dockerfile @@ -86,6 +86,18 @@ COPY grammar /var/alchemy/grammar COPY templates-profiler /var/alchemy/templates-profiler COPY templates /var/alchemy/templates COPY tests /var/alchemy/tests +RUN mkdir -p /var/alchemy/Phraseanet/logs \ + && chmod -R 777 /var/alchemy/Phraseanet/logs \ + && mkdir -p /var/alchemy/Phraseanet/cache \ + && chmod -R 777 /var/alchemy/Phraseanet/cache \ + && mkdir -p /var/alchemy/Phraseanet/datas \ + && chmod -R 777 /var/alchemy/Phraseanet/datas \ + && mkdir -p /var/alchemy/Phraseanet/tmp \ + && chmod -R 777 /var/alchemy/Phraseanet/tmp \ + && mkdir -p /var/alchemy/Phraseanet/www/custom \ + && chmod -R 777 /var/alchemy/Phraseanet/www/custom \ + && mkdir -p /var/alchemy/Phraseanet/config \ + && chmod -R 777 /var/alchemy/Phraseanet/config # Phraseanet FROM php:7.0-fpm-stretch as phraseanet-fpm @@ -129,6 +141,23 @@ RUN apt-get update \ && docker-php-source delete \ && rm -rf /var/lib/apt/lists/* +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ + && php -r "if (hash_file('sha384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \ + && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \ + && php -r "unlink('composer-setup.php');" + +# Node Installation (node + yarn) +# Reference : +# https://linuxize.com/post/how-to-install-node-js-on-ubuntu-18.04/ +# https://yarnpkg.com/lang/en/docs/install/#debian-stable +RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \ + && apt install -y nodejs \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ + && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ + && apt-get update && apt-get install -y --no-install-recommends yarn \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/ + RUN mkdir /entrypoint /var/alchemy \ && useradd -u 1000 app \ && mkdir -p /home/app/.composer \ @@ -136,18 +165,6 @@ RUN mkdir /entrypoint /var/alchemy \ COPY --from=builder --chown=app /var/alchemy /var/alchemy/Phraseanet ADD ./docker/phraseanet/ / -RUN mkdir -p /var/alchemy/Phraseanet/logs \ - && chmod -R 777 /var/alchemy/Phraseanet/logs \ - && mkdir -p /var/alchemy/Phraseanet/cache \ - && chmod -R 777 /var/alchemy/Phraseanet/cache \ - && mkdir -p /var/alchemy/Phraseanet/datas \ - && chmod -R 777 /var/alchemy/Phraseanet/datas \ - && mkdir -p /var/alchemy/Phraseanet/tmp \ - && chmod -R 777 /var/alchemy/Phraseanet/tmp \ - && mkdir -p /var/alchemy/Phraseanet/www/custom \ - && chmod -R 777 /var/alchemy/Phraseanet/www/custom \ - && mkdir -p /var/alchemy/Phraseanet/config \ - && chmod -R 777 /var/alchemy/Phraseanet/config WORKDIR /var/alchemy/Phraseanet ENTRYPOINT ["/phraseanet-entrypoint.sh"] CMD ["/boot.sh"] diff --git a/README.md b/README.md index 9fb4237d25..fb4b34870d 100644 --- a/README.md +++ b/README.md @@ -63,14 +63,12 @@ The docker distribution come with 3 differents containers : ## How to build -The three images can be built respectively with these commands : +You can build all the images with the following command at the root directory : - # nginx server - docker build --target phraseanet-nginx -t local/phraseanet-nginx . + ./build - # php-fpm application - docker build --target phraseanet-fpm -t local/phraseanet-fpm . - - # worker - docker build --target phraseanet-worker -t local/phraseanet-worker . +It will build and tag the following images : + local/phraseanet-worker: + local/phraseanet-fpm: + local/phraseanet-nginx: diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..0f983ccac4 --- /dev/null +++ b/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# nginx server +docker build --target phraseanet-nginx -t local/phraseanet-nginx:$1 . + +# php-fpm application +docker build --target phraseanet-fpm -t local/phraseanet-fpm:$1 . + +# worker +docker build --target phraseanet-worker -t local/phraseanet-worker:$1 . + diff --git a/docker/nginx/boot.sh b/docker/nginx/boot.sh index 49e6b8a3b7..2684d8c0f7 100755 --- a/docker/nginx/boot.sh +++ b/docker/nginx/boot.sh @@ -1,4 +1,6 @@ #!/bin/bash -cat nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" > /etc/nginx/nginx.conf +set -xe + +cat nginx.conf.sample | sed "s/\$MAX_BODY_SIZE/$MAX_BODY_SIZE/g" > /etc/nginx/conf.d/default.conf nginx -g "daemon off;" diff --git a/docker/nginx/etc/nginx/nginx.conf b/docker/nginx/etc/nginx/nginx.conf new file mode 100755 index 0000000000..71a94ee98f --- /dev/null +++ b/docker/nginx/etc/nginx/nginx.conf @@ -0,0 +1,31 @@ + +user app; +worker_processes 1; + +error_log /var/log/ngnix_error.log info; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; + +} diff --git a/docker/nginx/nginx.conf.sample b/docker/nginx/nginx.conf.sample index c1f0150c1e..ad015e7c5a 100644 --- a/docker/nginx/nginx.conf.sample +++ b/docker/nginx/nginx.conf.sample @@ -1,85 +1,39 @@ -user app; -worker_processes auto; - -#error_log /var/log/ngnix_error.log info; -error_log /dev/stdout info; - -pid /var/run/nginx.pid; -#daemon off; - -events { - worker_connections 1024; - multi_accept on; +upstream backend { + server phraseanet:9000; } -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - server_tokens off; +server { + listen 80; + root /var/alchemy/Phraseanet/www; - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; + index index.php; + client_max_body_size $MAX_BODY_SIZE; - access_log /dev/stdout main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - reset_timedout_connection on; - - proxy_connect_timeout 300s; - proxy_send_timeout 300s; - proxy_read_timeout 300s; - fastcgi_send_timeout 300s; - fastcgi_read_timeout 300; - - resolver 127.0.0.11; - - upstream backend { - server phraseanet:9000; + location /api { + rewrite ^(.*)$ /api.php/$1 last; } - server { - listen 80; - server_name localhost; - error_log on; - access_log on; - root /var/alchemy/Phraseanet/www; + location / { + # First attempt to serve request as file, then + # as directory, then fall back to index.html + try_files $uri $uri/ @rewriteapp; + } - index index.php; - client_max_body_size $MAX_BODY_SIZE; + location @rewriteapp { + rewrite ^(.*)$ /index.php/$1 last; + } - location /api { - rewrite ^(.*)$ /api.php/$1 last; - } + # PHP scripts -> PHP-FPM server listening on 127.0.0.1:9000 + location ~ ^/(index|index_dev|api)\.php(/|$) { + fastcgi_pass backend; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } - location / { - # First attempt to serve request as file, then - # as directory, then fall back to index.html - try_files $uri $uri/ @rewriteapp; - } - - location @rewriteapp { - rewrite ^(.*)$ /index.php/$1 last; - } - - # PHP scripts -> PHP-FPM server listening on 127.0.0.1:9000 - location ~ ^/(index|index_dev|api)\.php(/|$) { - fastcgi_pass backend; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - } - - location ~ ^/(status|ping)$ { - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_index index.php; - include fastcgi_params; - fastcgi_pass backend; - } + location ~ ^/(status|ping)$ { + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_pass backend; } } diff --git a/docker/phraseanet/boot.sh b/docker/phraseanet/boot.sh index 4b2cf2baa2..444b63a64c 100755 --- a/docker/phraseanet/boot.sh +++ b/docker/phraseanet/boot.sh @@ -1,5 +1,11 @@ #!/bin/bash +set -xe + +chown -R app:app /var/alchemy/Phraseanet/config +chown -R app:app /var/alchemy/Phraseanet/datas +chown -R app:app /var/alchemy/Phraseanet/tmp +chown -R app:app /var/alchemy/Phraseanet/www/thumbnails FILE=/var/alchemy/Phraseanet/config/configuration.yml if [ -f "$FILE" ]; then echo "$FILE exist, skip setup." diff --git a/docker/phraseanet/phraseanet-entrypoint.sh b/docker/phraseanet/phraseanet-entrypoint.sh index de763cd13a..225b56a672 100755 --- a/docker/phraseanet/phraseanet-entrypoint.sh +++ b/docker/phraseanet/phraseanet-entrypoint.sh @@ -5,4 +5,4 @@ set -e envsubst < /php.ini.sample > /usr/local/etc/php/php.ini envsubst < /php-fpm.conf.sample > /usr/local/etc/php-fpm.conf -docker-php-entrypoint $@ +bash -e docker-php-entrypoint $@ diff --git a/docker/phraseanet/worker-boot.sh b/docker/phraseanet/worker-boot.sh index 1b972c6cdb..4c1b76b02f 100755 --- a/docker/phraseanet/worker-boot.sh +++ b/docker/phraseanet/worker-boot.sh @@ -1,3 +1,4 @@ #!/bin/bash +mkdir /var/alchemy/Phraseanet/tmp/locks && chown -R app:app /var/alchemy/Phraseanet/tmp runuser app -c 'php /var/alchemy/Phraseanet/bin/console task-manager:scheduler:run' diff --git a/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php b/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php index 51ac40ab51..dc81bc67c3 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/FieldsController.php @@ -316,6 +316,7 @@ class FieldsController extends Controller ->set_tbranch($data['tbranch']) ->set_generate_cterms($data['generate_cterms']) ->set_gui_editable($data['gui_editable']) + ->set_gui_visible($data['gui_visible']) ->set_report($data['report']) ->setVocabularyControl(null) ->setVocabularyRestricted(false); @@ -351,7 +352,7 @@ class FieldsController extends Controller { return [ 'name', 'multi', 'thumbtitle', 'tag', 'business', 'indexable', 'aggregable', - 'required', 'separator', 'readonly', 'gui_editable', 'type', 'tbranch', 'generate_cterms', 'report', + 'required', 'separator', 'readonly', 'gui_editable', 'gui_visible' , 'type', 'tbranch', 'generate_cterms', 'report', 'vocabulary-type', 'vocabulary-restricted', 'dces-element', 'labels' ]; } diff --git a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php index 0c3bffb63e..9b8f4ed04d 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php +++ b/lib/Alchemy/Phrasea/Controller/Api/V1Controller.php @@ -596,6 +596,7 @@ class V1Controller extends Controller 'thesaurus_branch' => $databox_field->get_tbranch(), 'generate_cterms' => $databox_field->get_generate_cterms(), 'gui_editable' => $databox_field->get_gui_editable(), + 'gui_visible' => $databox_field->get_gui_visible(), 'type' => $databox_field->get_type(), 'indexable' => $databox_field->is_indexable(), 'multivalue' => $databox_field->is_multi(), diff --git a/lib/Alchemy/Phrasea/Controller/Prod/EditController.php b/lib/Alchemy/Phrasea/Controller/Prod/EditController.php index e164221a51..29ef942919 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/EditController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/EditController.php @@ -77,6 +77,7 @@ class EditController extends Controller 'tbranch' => $meta->get_tbranch(), 'generate_cterms' => $meta->get_generate_cterms(), 'gui_editable' => $meta->get_gui_editable(), + 'gui_visible' => $meta->get_gui_visible(), 'maxLength' => $meta->get_tag() ->getMaxLength(), 'minLength' => $meta->get_tag() diff --git a/lib/Alchemy/Phrasea/Core/Version.php b/lib/Alchemy/Phrasea/Core/Version.php index c525bf815c..19011867d9 100644 --- a/lib/Alchemy/Phrasea/Core/Version.php +++ b/lib/Alchemy/Phrasea/Core/Version.php @@ -16,7 +16,7 @@ class Version /** * @var string */ - private $number = '4.1.0-alpha.17a'; + private $number = '4.1.0-alpha.18a'; /** * @var string diff --git a/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php b/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php index 5f7e210a76..3e247d99c9 100644 --- a/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Field/DbalDataboxFieldRepository.php @@ -38,6 +38,7 @@ final class DbalDataboxFieldRepository implements DataboxFieldRepository 'label_nl', 'generate_cterms', 'gui_editable', + 'gui_visible', ]; /** @var DataboxFieldFactory */ diff --git a/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php b/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php index c39271db6a..efbf36fe81 100644 --- a/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php +++ b/lib/Alchemy/Phrasea/Twig/PhraseanetExtension.php @@ -48,6 +48,7 @@ class PhraseanetExtension extends \Twig_Extension new \Twig_SimpleFunction('border_checker_from_fqcn', array($this, 'getCheckerFromFQCN')), new \Twig_SimpleFunction('caption_field', array($this, 'getCaptionField')), new \Twig_SimpleFunction('caption_field_label', array($this, 'getCaptionFieldLabel')), + new \Twig_SimpleFunction('caption_field_gui_visible', array($this, 'getCaptionFieldGuiVisible')), new \Twig_SimpleFunction('caption_field_order', array($this, 'getCaptionFieldOrder')), new \Twig_SimpleFunction('flag_slugify', array(Flag::class, 'normalizeName')), @@ -77,6 +78,29 @@ class PhraseanetExtension extends \Twig_Extension return ''; } + /** + * get localized field's gui_visible + * @param RecordInterface $record + * @param $fieldName + * @return string - the name gui_visible + */ + public function getCaptionFieldGuiVisible(RecordInterface $record, $fieldName) + { + if ($record) { + /** @var \appbox $appbox */ + $appbox = $this->app['phraseanet.appbox']; + $databox = $appbox->get_databox($record->getDataboxId()); + foreach ($databox->get_meta_structure() as $meta) { + /** @var \databox_field $meta */ + if ($meta->get_name() === $fieldName) { + return $meta->get_gui_visible($this->app['locale']); + } + } + } + + return ''; + } + public function getCaptionField(RecordInterface $record, $field, $value) { if ($record instanceof ElasticsearchRecord) { diff --git a/lib/classes/databox.php b/lib/classes/databox.php index 01aa2eea31..c961f1e58c 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -464,6 +464,7 @@ class databox extends base implements ThumbnailedElement ->set_tbranch(isset($field['tbranch']) ? (string) $field['tbranch'] : '') ->set_generate_cterms((isset($field['generate_cterms']) && (string) $field['generate_cterms'] == 1)) ->set_gui_editable((isset($field['gui_editable']) && (string) $field['gui_editable'] == 1)) + ->set_gui_visible((isset($field['gui_editable']) && (string) $field['gui_visible'] == 1)) ->set_thumbtitle(isset($field['thumbtitle']) ? (string) $field['thumbtitle'] : (isset($field['thumbTitle']) ? $field['thumbTitle'] : '0')) ->set_report(isset($field['report']) ? (string) $field['report'] : '1') ->save(); diff --git a/lib/classes/databox/field.php b/lib/classes/databox/field.php index 09dab67d46..85e9089cad 100644 --- a/lib/classes/databox/field.php +++ b/lib/classes/databox/field.php @@ -45,6 +45,7 @@ class databox_field implements cache_cacheableInterface protected $tbranch; protected $generate_cterms; protected $gui_editable; + protected $gui_visible; protected $separator; protected $thumbtitle; @@ -170,6 +171,7 @@ class databox_field implements cache_cacheableInterface $this->tbranch = $row['tbranch']; $this->generate_cterms = (bool)$row['generate_cterms']; $this->gui_editable = (bool)$row['gui_editable']; + $this->gui_visible = (bool)$row['gui_visible']; $this->VocabularyType = $row['VocabularyControlType']; $this->VocabularyRestriction = (bool)$row['RestrictToVocabularyControl']; @@ -312,6 +314,7 @@ class databox_field implements cache_cacheableInterface `tbranch` = :tbranch, `generate_cterms` = :generate_cterms, `gui_editable` = :gui_editable, + `gui_visible` = :gui_visible, `sorter` = :position, `thumbtitle` = :thumbtitle, `VocabularyControlType` = :VocabularyControlType, @@ -337,6 +340,7 @@ class databox_field implements cache_cacheableInterface ':tbranch' => $this->tbranch, ':generate_cterms' => $this->generate_cterms ? '1' : '0', ':gui_editable' => $this->gui_editable ? '1' : '0', + ':gui_visible' => $this->gui_visible ? '1' : '0', ':position' => $this->position, ':thumbtitle' => $this->thumbtitle, ':VocabularyControlType' => $this->getVocabularyControl() ? $this->getVocabularyControl()->getType() : null, @@ -390,6 +394,7 @@ class databox_field implements cache_cacheableInterface $meta->setAttribute('tbranch', $this->tbranch); $meta->setAttribute('generate_cterms', $this->generate_cterms ? '1' : '0'); $meta->setAttribute('gui_editable', $this->gui_editable ? '1' : '0'); + $meta->setAttribute('gui_visible', $this->gui_visible ? '1' : '0'); if ($this->multi) { $meta->setAttribute('separator', $this->separator); } @@ -743,6 +748,17 @@ class databox_field implements cache_cacheableInterface return $this; } + /** + * @param boolean $gui_visible + * @return databox_field + */ + public function set_gui_visible($gui_visible) + { + $this->gui_visible = $gui_visible; + + return $this; + } + /** * * @param string $separator @@ -845,6 +861,15 @@ class databox_field implements cache_cacheableInterface return $this->gui_editable; } + /** + * + * @return boolean + */ + public function get_gui_visible() + { + return $this->gui_visible; + } + /** * @param Boolean $all If set to false, returns a one-char separator to use for serialiation * @@ -957,6 +982,7 @@ class databox_field implements cache_cacheableInterface 'tbranch' => $this->tbranch, 'generate_cterms' => $this->generate_cterms, 'gui_editable' => $this->gui_editable, + 'gui_visible' => $this->gui_visible, 'separator' => $this->separator, 'required' => $this->required, 'report' => $this->report, @@ -995,10 +1021,10 @@ class databox_field implements cache_cacheableInterface } $sql = "INSERT INTO metadatas_structure - (`id`, `name`, `src`, `readonly`, `gui_editable`, `required`, `indexable`, `type`, `tbranch`, `generate_cterms`, + (`id`, `name`, `src`, `readonly`, `gui_editable`,`gui_visible`, `required`, `indexable`, `type`, `tbranch`, `generate_cterms`, `thumbtitle`, `multi`, `business`, `aggregable`, `report`, `sorter`, `separator`) - VALUES (null, :name, '', 0, 1, 0, 1, 'string', '', 1, + VALUES (null, :name, '', 0, 1, 1, 0, 1, 'string', '', 1, null, 0, 0, 0, 1, :sorter, '')"; diff --git a/lib/conf.d/bases_structure.xml b/lib/conf.d/bases_structure.xml index b989e2f9d6..8cfcd692fd 100644 --- a/lib/conf.d/bases_structure.xml +++ b/lib/conf.d/bases_structure.xml @@ -2049,6 +2049,14 @@ 1 + + gui_visible + int(1) unsigned + + + 1 + + diff --git a/templates/web/admin/fields/templates.html.twig b/templates/web/admin/fields/templates.html.twig index 191f3f18b8..f0757d3d37 100644 --- a/templates/web/admin/fields/templates.html.twig +++ b/templates/web/admin/fields/templates.html.twig @@ -197,6 +197,14 @@ + + + + +