diff --git a/CHANGELOG.md b/CHANGELOG.md index db246efb2..355a69d02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,10 +65,34 @@ Version 1.5.10 - allow to group export in UI -Branch CRUD-Init -================ +Version 1.5.11 +============== +- improve return path functions and filters ; + +Version 1.5.12 +============== + +- make the redirection to admin temporarily: some admin experienced cache problems (403 error) when they switched from one admin account to a non-admin one ; + +Version 1.5.13 +============== + +- allow to customize logo on login screen and main layout ; +- remove desert background image on page, handle it from cache in login screen; + +Version 1.5.14 +============== + +- fix errors in pagination +- fix search: usage of parenthesis +- add DQL function REPLACE for replacing in strings: "REPLACE(string, 'from', 'to')" +- add function to format phonenumber - improve `chill_print_or_message` to support date time; - add a module `show_hide` for javascript; - load assets using functions ; - load a `runtime.js` assets for objects shared by webpack ; + +Branch CRUD-Init +================ + diff --git a/Controller/DefaultController.php b/Controller/DefaultController.php index ba44375ed..b10bf0d23 100644 --- a/Controller/DefaultController.php +++ b/Controller/DefaultController.php @@ -10,7 +10,7 @@ class DefaultController extends Controller { if ($this->isGranted('ROLE_ADMIN')) { - return $this->redirectToRoute('chill_main_admin_central'); + return $this->redirectToRoute('chill_main_admin_central', [], 302); } return $this->render('ChillMainBundle::layout.html.twig'); diff --git a/DependencyInjection/ChillMainExtension.php b/DependencyInjection/ChillMainExtension.php index 92bc8ce9c..af83e4c12 100644 --- a/DependencyInjection/ChillMainExtension.php +++ b/DependencyInjection/ChillMainExtension.php @@ -34,6 +34,7 @@ use Chill\MainBundle\Doctrine\DQL\Similarity; use Chill\MainBundle\Doctrine\DQL\OverlapsI; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; +use Chill\MainBundle\Doctrine\DQL\Replace; /** * This class load config for chillMainExtension. @@ -164,7 +165,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, 'string_functions' => array( 'unaccent' => Unaccent::class, 'GET_JSON_FIELD_BY_KEY' => GetJsonFieldByKey::class, - 'AGGREGATE' => JsonAggregate::class + 'AGGREGATE' => JsonAggregate::class, + 'REPLACE' => Replace::class, ), 'numeric_functions' => [ 'JSONB_EXISTS_IN_ARRAY' => JsonbExistsInArray::class, diff --git a/Doctrine/DQL/Replace.php b/Doctrine/DQL/Replace.php new file mode 100644 index 000000000..6d30ec7d9 --- /dev/null +++ b/Doctrine/DQL/Replace.php @@ -0,0 +1,64 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Doctrine\DQL; + +use Doctrine\ORM\Query\AST\Functions\FunctionNode; +use Doctrine\ORM\Query\Lexer; + +/** + * + * + */ +class Replace extends FunctionNode +{ + protected $string; + + protected $from; + + protected $to; + + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker): string + { + return 'REPLACE('. + $this->string->dispatch($sqlWalker). + ', '. + $this->from->dispatch($sqlWalker). + ', '. + $this->to->dispatch($sqlWalker). + ')'; + } + + public function parse(\Doctrine\ORM\Query\Parser $parser): void + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->string = $parser->StringPrimary(); + + $parser->match(Lexer::T_COMMA); + + $this->from = $parser->StringPrimary(); + + $parser->match(Lexer::T_COMMA); + + $this->to = $parser->StringPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/Pagination/Page.php b/Pagination/Page.php index 2cf400e4e..e6b3943ed 100644 --- a/Pagination/Page.php +++ b/Pagination/Page.php @@ -63,6 +63,13 @@ class Page implements PageInterface * @var int */ protected $itemPerPage; + + /** + * The number of items in the whole iteration + * + * @var int + */ + protected $totalItems; public function __construct( @@ -70,13 +77,15 @@ class Page implements PageInterface $itemPerPage, UrlGeneratorInterface $urlGenerator, $route, - array $routeParameters + array $routeParameters, + $totalItems ) { $this->urlGenerator = $urlGenerator; $this->number = $number; $this->itemPerPage = $itemPerPage; $this->route = $route; $this->routeParameters = $routeParameters; + $this->totalItems = $totalItems; } public function generateUrl() @@ -91,7 +100,9 @@ class Page implements PageInterface public function getLastItemNumber() { - return $this->number * $this->itemPerPage - 1; + $last = $this->number * $this->itemPerPage - 1; + + return $last < $this->totalItems ? $last : $this->totalItems; } public function getNumber() diff --git a/Pagination/Paginator.php b/Pagination/Paginator.php index 54b71799c..82577d078 100644 --- a/Pagination/Paginator.php +++ b/Pagination/Paginator.php @@ -232,7 +232,8 @@ class Paginator implements PaginatorInterface array_merge($this->routeParameters, array( $this->pageKey => $number, $this->itemPerPageKey => $this->itemPerPage - )) + )), + $this->totalItems ); } diff --git a/Phonenumber/PhonenumberHelper.php b/Phonenumber/PhonenumberHelper.php index 772b43945..4e06472d3 100644 --- a/Phonenumber/PhonenumberHelper.php +++ b/Phonenumber/PhonenumberHelper.php @@ -53,6 +53,7 @@ class PhonenumberHelper protected $cachePool; const LOOKUP_URI = 'https://lookups.twilio.com/v1/PhoneNumbers/%s'; + const FORMAT_URI = 'https://lookups.twilio.com/v1/PhoneNumbers/%s'; public function __construct( @@ -121,6 +122,64 @@ class PhonenumberHelper return \in_array($validation, [ 'landline', 'voip' ]); } + public function format($phonenumber) + { + return $this->performTwilioFormat($phonenumber); + } + + protected function performTwilioFormat($phonenumber) + { + if (FALSE === $this->isPhonenumberValidationConfigured()) { + return $phonenumber; + } + + // filter only number + $filtered = \preg_replace("/[^0-9]/", "", $phonenumber); + + $item = $this->cachePool->getItem('pnum_format_nat_'.$filtered); + + if ($item->isHit()) { + return $item->get(); + } + + try { + $response = $this->twilioClient->get(sprintf(self::FORMAT_URI, '+'.$filtered), [ + 'http_errors' => true, + ]); + + } catch (ClientException $e) { + $this->logger->error("[phonenumber helper] Could not format number " + . "due to client error", [ + "message" => $e->getResponseBodySummary($e->getResponse()), + "status_code" => $e->getResponse()->getStatusCode(), + "phonenumber" => $phonenumber + ]); + + return $phonenumber; + } catch (ServerException $e) { + $this->logger->error("[phonenumber helper] Could not format number " + . "due to server error", [ + "message" => $e->getResponseBodySummary($e->getResponse()), + "status_code" => $e->getResponse()->getStatusCode(), + "phonenumber" => $phonenumber + ]); + + return null; + } + + $format = \json_decode($response->getBody())->national_format; + + $item + ->set($format) + // expires after 3d + ->expiresAfter(3600 * 24 * 3) + ; + + $this->cachePool->save($item); + + return $format; + } + protected function performTwilioLookup($phonenumber) { if (FALSE === $this->isPhonenumberValidationConfigured()) { diff --git a/Phonenumber/Templating.php b/Phonenumber/Templating.php new file mode 100644 index 000000000..daaee8956 --- /dev/null +++ b/Phonenumber/Templating.php @@ -0,0 +1,52 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Phonenumber; + +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; +use Chill\MainBundle\Phonenumber\PhonenumberHelper; + +/** + * + * + */ +class Templating extends AbstractExtension +{ + /** + * + * @var PhonenumberHelper + */ + protected $phonenumberHelper; + + public function __construct(PhonenumberHelper $phonenumberHelper) + { + $this->phonenumberHelper = $phonenumberHelper; + } + + public function getFilters() + { + return [ + new TwigFilter('chill_format_phonenumber', [$this, 'formatPhonenumber']) + ]; + } + + public function formatPhonenumber($phonenumber) + { + return $this->phonenumberHelper->format($phonenumber); + } +} diff --git a/Resources/config/routing.yml b/Resources/config/routing.yml index 9ac1d255c..c6ab5918e 100644 --- a/Resources/config/routing.yml +++ b/Resources/config/routing.yml @@ -35,7 +35,7 @@ root: defaults: _controller: FrameworkBundle:Redirect:urlRedirect path: /homepage - permanent: true + permanent: false chill_main_homepage_without_locale: path: /homepage diff --git a/Resources/config/services/phonenumber.yml b/Resources/config/services/phonenumber.yml index ec519c836..f297c03e0 100644 --- a/Resources/config/services/phonenumber.yml +++ b/Resources/config/services/phonenumber.yml @@ -4,6 +4,12 @@ services: $logger: '@Psr\Log\LoggerInterface' $config: '%chill_main.phone_helper%' $cachePool: '@cache.user_data' + + Chill\MainBundle\Phonenumber\Templating: + arguments: + $phonenumberHelper: '@Chill\MainBundle\Phonenumber\PhonenumberHelper' + tags: + - { name: twig.extension } Chill\MainBundle\Validation\Validator\ValidPhonenumber: arguments: diff --git a/Resources/public/main.js b/Resources/public/main.js index 50d4e9740..ffbe55c46 100644 --- a/Resources/public/main.js +++ b/Resources/public/main.js @@ -27,8 +27,6 @@ require('./modules/download-report/index.js'); require('select2/dist/css/select2.css'); require('./modules/select_interactive_loading/index.js'); require('./modules/export-list/export-list.scss'); -//import {ChillShowHide} from './modules/show_hide/index.js'; -//global.ChillShowHide = ChillShowHide; // img require('./img/favicon.ico'); diff --git a/Resources/public/modules/login_page/desert.jpg b/Resources/public/modules/login_page/desert.jpg new file mode 100644 index 000000000..6872698f2 Binary files /dev/null and b/Resources/public/modules/login_page/desert.jpg differ diff --git a/Resources/public/modules/login_page/login.scss b/Resources/public/modules/login_page/login.scss index b22592159..e9662c5df 100644 --- a/Resources/public/modules/login_page/login.scss +++ b/Resources/public/modules/login_page/login.scss @@ -28,7 +28,7 @@ body { right: 0; top: 0; z-index: -1; - background-image: url('./../../img/background/desert.jpg'); + background-image: url('./desert.jpg'); background-attachment: fixed; background-repeat: no-repeat; background-size: cover; diff --git a/Resources/views/Layout/_header-logo.html.twig b/Resources/views/Layout/_header-logo.html.twig new file mode 100644 index 000000000..be59b454f --- /dev/null +++ b/Resources/views/Layout/_header-logo.html.twig @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Resources/views/Login/_login-logo.html.twig b/Resources/views/Login/_login-logo.html.twig new file mode 100644 index 000000000..751165357 --- /dev/null +++ b/Resources/views/Login/_login-logo.html.twig @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Resources/views/Login/login.html.twig b/Resources/views/Login/login.html.twig index 54d5ae26c..de57ba4d2 100644 --- a/Resources/views/Login/login.html.twig +++ b/Resources/views/Login/login.html.twig @@ -27,8 +27,8 @@
- - + {{ include('@ChillMain/Login/_login-logo.html.twig') }} + {% if error is not null %}

{{ error.message|trans }}

{% endif %} diff --git a/Resources/views/layout.html.twig b/Resources/views/layout.html.twig index 3029516d5..9baba0fb5 100644 --- a/Resources/views/layout.html.twig +++ b/Resources/views/layout.html.twig @@ -37,7 +37,7 @@ diff --git a/Search/AbstractSearch.php b/Search/AbstractSearch.php index 61d787e34..942819a39 100644 --- a/Search/AbstractSearch.php +++ b/Search/AbstractSearch.php @@ -76,7 +76,14 @@ abstract class AbstractSearch implements SearchInterface foreach ($supportedTerms as $term) { if (array_key_exists($term, $terms) && $term !== '_default') { $recomposed .= ' '.$term.':'; + $containsSpace = \strpos($terms[$term], " ") !== false; + if ($containsSpace) { + $recomposed .= "("; + } $recomposed .= (mb_stristr(' ', $terms[$term]) === FALSE) ? $terms[$term] : '('.$terms[$term].')'; + if ($containsSpace) { + $recomposed .= ")"; + } } } diff --git a/Templating/ChillTwigRoutingHelper.php b/Templating/ChillTwigRoutingHelper.php index 6e9bc900f..5bbd6abe2 100644 --- a/Templating/ChillTwigRoutingHelper.php +++ b/Templating/ChillTwigRoutingHelper.php @@ -5,6 +5,7 @@ namespace Chill\MainBundle\Templating; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; +use Twig\TwigFilter; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Bridge\Twig\Extension\RoutingExtension; @@ -42,7 +43,15 @@ class ChillTwigRoutingHelper extends AbstractExtension return [ new TwigFunction('chill_return_path_or', [$this, 'getReturnPathOr'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']] ), new TwigFunction('chill_path_add_return_path', [$this, 'getPathAddReturnPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']] ), - new TwigFunction('chill_path_forward_return_path', [$this, 'getPathForwardReturnPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']] ) + new TwigFunction('chill_path_forward_return_path', [$this, 'getPathForwardReturnPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']] ), + + ]; + } + + public function getFilters() + { + return [ + new TwigFilter('chill_return_path_label', [$this, 'getLabelReturnPath']), ]; } @@ -51,6 +60,13 @@ class ChillTwigRoutingHelper extends AbstractExtension return $this->originalExtension->isUrlGenerationSafe($argsNode); } + public function getLabelReturnPath($default) + { + $request = $this->requestStack->getCurrentRequest(); + + return $request->query->get('returnPathLabel', null) ?? $default; + } + /** * Return the return path if it exists, or generate the path if not. * @@ -78,12 +94,16 @@ class ChillTwigRoutingHelper extends AbstractExtension * @param bool $relative * @return string */ - public function getPathAddReturnPath($name, $parameters = [], $relative = false) + public function getPathAddReturnPath($name, $parameters = [], $relative = false, $label = null) { $request = $this->requestStack->getCurrentRequest(); $parameters['returnPath'] = $request->getRequestUri(); + if ($label) { + $parameters['returnPathLabel'] = $label; + } + return $this->originalExtension->getPath($name, $parameters, $relative); } diff --git a/chill.webpack.config.js b/chill.webpack.config.js index 9fcfd0640..572db8d6c 100644 --- a/chill.webpack.config.js +++ b/chill.webpack.config.js @@ -5,4 +5,4 @@ module.exports = function(encore, entries) { encore.addAliases({ ShowHide: __dirname + '/Resources/public/modules/show_hide/' }); -}; \ No newline at end of file +};