diff --git a/.github/workflows/behavioural_tests.yaml b/.github/workflows/behavioural_tests.yaml index 41975077f..da3c0888a 100644 --- a/.github/workflows/behavioural_tests.yaml +++ b/.github/workflows/behavioural_tests.yaml @@ -20,6 +20,8 @@ jobs: php-version: ${{ matrix.php-version }} extensions: json, mbstring, pdo, curl, pdo_sqlite coverage: none + # See https://github.community/t/sudo-apt-install-fails-with-failed-to-fetch-http-security-ubuntu-com-404-not-found-ip/17075 + - run: sudo apt update - name: Install dependencies run: | sudo composer self-update -q @@ -69,6 +71,8 @@ jobs: - uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} + # See https://github.community/t/sudo-apt-install-fails-with-failed-to-fetch-http-security-ubuntu-com-404-not-found-ip/17075 + - run: sudo apt update - name: Install dependencies run: | sudo composer self-update -q diff --git a/src/Controller/Frontend/ListingController.php b/src/Controller/Frontend/ListingController.php index 9f01b3902..497d2a6ed 100644 --- a/src/Controller/Frontend/ListingController.php +++ b/src/Controller/Frontend/ListingController.php @@ -59,13 +59,7 @@ public function listing(ContentRepository $contentRepository, string $contentTyp $page = (int) $this->getFromRequest('page', '1'); $amountPerPage = $contentType->get('listing_records'); - $order = $this->getFromRequest('order', $contentType->get('order')); - $queryParams = $this->parseQueryParams($this->request, $contentType); - - $params = array_merge($queryParams, [ - 'status' => 'published', - 'order' => $order, - ]); + $params = $this->parseQueryParams($this->request, $contentType); /** @var Content|Pagerfanta $content */ $content = $this->query->getContent($contentTypeSlug, $params); @@ -105,14 +99,22 @@ public function listing(ContentRepository $contentRepository, string $contentTyp private function parseQueryParams(Request $request, ContentType $contentType): array { if ($this->config->get('general/query_search') === false) { - return []; + return [ + 'order' => $contentType->get('order'), + 'status' => 'published', + ]; } $queryParams = collect($request->query->all()); - $allowedParams = array_merge($contentType['fields']->keys()->all(), $contentType['taxonomy']->all(), ['order']); + // Note, we're not including 'limit', 'printquery', 'returnsingle' or 'returnmultiple' on purpose + $allowedParams = array_merge( + $contentType['fields']->keys()->all(), + $contentType['taxonomy']->all(), + ['order', 'earliest', 'latest', 'offset', 'page', 'random', 'author'] + ); - return $queryParams->mapWithKeys(function ($value, $key) use ($allowedParams) { + $params = $queryParams->mapWithKeys(function ($value, $key) use ($allowedParams) { // Ensure we don't have arrays, if we get something like `title[]=…` passed in. if (is_array($value)) { $value = current($value); @@ -125,6 +127,15 @@ private function parseQueryParams(Request $request, ContentType $contentType): a return in_array($key, $allowedParams, true) ? [$key => $value] : []; })->toArray(); + + if (! array_key_exists('order', $params)) { + $params['order'] = $contentType->get('order'); + } + + // Ensure we only list things that are 'published' + $params['status'] = 'published'; + + return $params; } private function setRecords($content, int $amountPerPage, int $page): Pagerfanta diff --git a/src/Repository/ContentRepository.php b/src/Repository/ContentRepository.php index 6cc03a9ab..15caee391 100644 --- a/src/Repository/ContentRepository.php +++ b/src/Repository/ContentRepository.php @@ -4,6 +4,7 @@ namespace Bolt\Repository; +use Bolt\Common\Str; use Bolt\Configuration\Content\ContentType; use Bolt\Doctrine\JsonHelper; use Bolt\Entity\Content; @@ -99,6 +100,10 @@ public function searchNaive(string $searchTerm, int $page, int $amountPerPage, C $connection = $qb->getEntityManager()->getConnection(); [$where] = JsonHelper::wrapJsonFunction('t.value', $searchTerm, $connection); + // Rather than searching for '%foo bar%', search '%foo%bar%' which doesn't require + // an exact match, but requires 'foo' to appear before 'bar'. + $searchTerm = str_replace(' ', '%', Str::cleanWhitespace($searchTerm)); + // The search term must match the format of the content in the database // Therefore, it is JSON encoded and escaped with backslashes $encodedSearchTerm = addslashes(trim(json_encode($searchTerm), '"')); diff --git a/src/Twig/ContentExtension.php b/src/Twig/ContentExtension.php index c19710900..99e4c48fb 100644 --- a/src/Twig/ContentExtension.php +++ b/src/Twig/ContentExtension.php @@ -257,7 +257,7 @@ public function getExcerpt($content, int $length = 280, bool $includeTitle = fal } if (ContentHelper::isSuitable($content, 'excerpt_format')) { - $excerpt = $this->contentHelper->get($content, $content->getDefinition()->get('excerpt_format')); + $excerpt = $this->contentHelper->get($content, $content->getDefinition()->get('excerpt_format'), $this->request->getLocale()); } else { $excerpt = $this->getFieldBasedExcerpt($content, $length, $includeTitle); }