diff --git a/composer.json b/composer.json index d10812b4..364a2417 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "description": "Bolt 4 skeleton / prototype", "require": { "php": "^7.1.3", - "ext-pdo_sqlite": "*", + "ext-json": "*", "api-platform/api-pack": "^1.1", "bolt/common": "^2.0", "cocur/slugify": "^3.1", @@ -43,6 +43,7 @@ "white-october/pagerfanta-bundle": "^1.1" }, "require-dev": { + "ext-pdo_sqlite": "*", "dama/doctrine-test-bundle": "^5.0", "doctrine/doctrine-fixtures-bundle": "^3.0", "friendsofphp/php-cs-fixer": "^2.12", diff --git a/phpstan.neon b/phpstan.neon index 0dc6084c..f09c3a76 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,6 @@ parameters: tmpDir: var/cache/ecs - level: 3 + level: 5 includes: # - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon # make ON when thecodingmachine/safe will get stable \ No newline at end of file diff --git a/src/Command/DeleteUserCommand.php b/src/Command/DeleteUserCommand.php index 4b8701a6..81544452 100644 --- a/src/Command/DeleteUserCommand.php +++ b/src/Command/DeleteUserCommand.php @@ -106,10 +106,9 @@ HELP { $username = $this->validator->validateUsername($input->getArgument('username')); - /** @var User $user */ - $user = $this->users->findOneByUsername($username); + $user = $this->users->findOneBy(['username' => $username]); - if ($user === null) { + if (! $user instanceof User) { throw new RuntimeException(sprintf('User with username "%s" not found.', $username)); } diff --git a/src/Configuration/Parser/GeneralParser.php b/src/Configuration/Parser/GeneralParser.php index bc279035..447b2db9 100644 --- a/src/Configuration/Parser/GeneralParser.php +++ b/src/Configuration/Parser/GeneralParser.php @@ -23,7 +23,7 @@ class GeneralParser extends BaseParser $general = Arr::replaceRecursive($defaultconfig, Arr::replaceRecursive($tempconfig, $tempconfiglocal)); // Make sure Bolt's mount point is OK: - $general['branding']['path'] = '/' . Str::makeSafe($general['branding']['path']); + $general['branding']['path'] = '/' . Str::makeSafe((string) $general['branding']['path']); // Set the link in branding, if provided_by is set. $general['branding']['provided_link'] = Html::providerLink( @@ -156,7 +156,7 @@ class GeneralParser extends BaseParser /** * Parse and fine-tune the database configuration. */ - protected function parseDatabase(array $options): Collection + protected function parseDatabase(array $options): array { // Make sure prefix ends with underscore if (mb_substr($options['prefix'], mb_strlen($options['prefix']) - 1) !== '_') { @@ -166,7 +166,7 @@ class GeneralParser extends BaseParser // Parse master connection parameters $master = $this->parseConnectionParams($options); // Merge master connection into options - $options = collect($options)->merge($master); + $options = collect($options)->merge($master)->toArray(); // Add platform specific random functions $driver = \Bolt\Common\Str::replaceFirst($options['driver'], 'pdo_', ''); @@ -215,9 +215,9 @@ class GeneralParser extends BaseParser * - Bolt keys are converted to Doctrine keys * - Invalid keys are filtered out * - * @param array $defaults + * @param array|string $params */ - protected function parseConnectionParams(array $params, $defaults = []): Collection + protected function parseConnectionParams($params, ?Collection $defaults = null): Collection { // Handle host shortcut if (is_string($params)) { @@ -236,8 +236,10 @@ class GeneralParser extends BaseParser } } - // Merge in defaults - $params = collect($defaults)->merge($params); + // Merge with defaults + if ($defaults !== null) { + $params = $defaults->merge($params); + } // Filter out invalid keys $validKeys = [ @@ -254,13 +256,13 @@ class GeneralParser extends BaseParser /** * Fine-tune Sqlite configuration parameters. */ - protected function parseSqliteOptions(array $config): Collection + protected function parseSqliteOptions(array $config): array { if (isset($config['memory']) && $config['memory']) { // If in-memory, no need to parse paths unset($config['path']); - return collect($config); + return $config; } // Prevent SQLite driver from trying to use in-memory connection unset($config['memory']); @@ -275,7 +277,7 @@ class GeneralParser extends BaseParser if (Path::hasExtension($path)) { $config['path'] = $path; - return collect($config); + return $config; } // Use database name for filename @@ -287,6 +289,6 @@ class GeneralParser extends BaseParser // Join filename with database path $config['path'] = Path::join($path, $filename); - return collect($config); + return $config; } } diff --git a/src/Content/MediaFactory.php b/src/Content/MediaFactory.php index 234ba3fa..bc91dae8 100644 --- a/src/Content/MediaFactory.php +++ b/src/Content/MediaFactory.php @@ -10,11 +10,11 @@ use Bolt\Repository\MediaRepository; use Carbon\Carbon; use Faker\Factory; use Faker\Generator; +use PHPExif\Exif; use PHPExif\Reader\Reader; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Finder\SplFileInfo; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; -use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; use Tightenco\Collect\Support\Collection; class MediaFactory @@ -88,11 +88,12 @@ class MediaFactory return $media; } - private function updateImageData(Media $media, $file): void + private function updateImageData(Media $media, SplFileInfo $file): void { + /** @var Exif|bool $exif */ $exif = $this->exif->read($file->getRealPath()); - if ($exif) { + if ($exif instanceof Exif) { $media->setWidth($exif->getWidth()) ->setHeight($exif->getHeight()); @@ -128,7 +129,6 @@ class MediaFactory /** @var TokenStorage $tokenStorage */ $tokenStorage = $this->container->get('security.token_storage'); - /** @var PostAuthenticationGuardToken $token */ $token = $tokenStorage->getToken(); if ($token === null) { return null; diff --git a/src/DataFixtures/ContentFixtures.php b/src/DataFixtures/ContentFixtures.php index b876e2b0..df0b8a0f 100644 --- a/src/DataFixtures/ContentFixtures.php +++ b/src/DataFixtures/ContentFixtures.php @@ -7,6 +7,7 @@ namespace Bolt\DataFixtures; use Bolt\Configuration\Config; use Bolt\Entity\Content; use Bolt\Entity\Field; +use Bolt\Entity\User; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; use Doctrine\Common\Persistence\ObjectManager; @@ -51,6 +52,7 @@ class ContentFixtures extends Fixture implements DependentFixtureInterface foreach (range(1, $amount) as $i) { $ref = $i === 0 ? 'admin' : ['admin', 'henkie', 'jane_admin', 'tom_admin'][random_int(0, 3)]; + /** @var User $author */ $author = $this->getReference($ref); $content = new Content(); diff --git a/src/Entity/ContentMagicTraits.php b/src/Entity/ContentMagicTraits.php index ff8667aa..113591ef 100644 --- a/src/Entity/ContentMagicTraits.php +++ b/src/Entity/ContentMagicTraits.php @@ -11,7 +11,7 @@ trait ContentMagicTraits { public function __toString(): string { - return (string) 'Content # ' . $this->getId(); + return 'Content # ' . (string) $this->getId(); } /** @@ -142,7 +142,10 @@ trait ContentMagicTraits ]; } - public function magicExcerpt($length = 150, $includeTitle = true, $focus = null): Twig_Markup + /** + * @param string|array|null $focus + */ + public function magicExcerpt(int $length = 150, bool $includeTitle = true, $focus = null): Twig_Markup { $excerpter = new Excerpt($this); $excerpt = $excerpter->getExcerpt($length, $includeTitle, $focus); diff --git a/src/Helpers/Excerpt.php b/src/Helpers/Excerpt.php index 712be753..cc8558bf 100644 --- a/src/Helpers/Excerpt.php +++ b/src/Helpers/Excerpt.php @@ -18,9 +18,8 @@ class Excerpt * Constructor. * * @param Content|string $content - * @param string|null $title */ - public function __construct($content, $title = null) + public function __construct($content, ?string $title = null) { $this->content = $content; $this->title = $title; @@ -28,14 +27,16 @@ class Excerpt /** * Get the excerpt of a given piece of text. + * + * @param string|array|null $focus */ - public function getExcerpt(int $length = 200, bool $includeTitle = false, ?string $focus = null): string + public function getExcerpt(int $length = 200, bool $includeTitle = false, $focus = null): string { $title = null; $excerpt = ''; if ($includeTitle && $this->content->magicTitle() !== null) { - $title = Html::trimText((string) $this->content->magicTitle(), $length); + $title = Html::trimText($this->content->magicTitle(), $length); $length -= mb_strlen($title); } @@ -48,15 +49,15 @@ class Excerpt } } } else { - $excerpt = (string) $this->content; + $excerpt = $this->content; } $excerpt = str_replace('>', '> ', $excerpt); - if (! $focus) { - $excerpt = Html::trimText($excerpt, $length); - } else { + if ($focus) { $excerpt = $this->extractRelevant($focus, $excerpt, $length); + } else { + $excerpt = Html::trimText($excerpt, $length); } if (! empty($title)) { @@ -95,10 +96,8 @@ class Excerpt * When checking for matches we only change the location if there is a better match. * The only exception is where we have only two matches in which case we just take the * first as will be equally distant. - * - * @param int $prevCount */ - private function determineSnipLocation(array $locations, $prevCount): int + private function determineSnipLocation(array $locations, int $prevCount): int { // If we only have 1 match we don't actually do the for loop so set to the first $startPos = (int) reset($locations); @@ -131,10 +130,8 @@ class Excerpt * @see: http://www.boyter.org/2013/04/building-a-search-result-extract-generator-in-php/ * * @param string|array $words - * @param string $fulltext - * @param int $relLength */ - private function extractRelevant($words, $fulltext, $relLength = 300): string + private function extractRelevant($words, string $fulltext, int $relLength = 300): string { $fulltext = strip_tags($fulltext); @@ -144,7 +141,7 @@ class Excerpt // 1/6 ratio on prevcount tends to work pretty well and puts the terms // in the middle of the extract - $prevCount = floor($relLength / 6); + $prevCount = (int) floor($relLength / 6); $indicator = '…'; @@ -158,10 +155,10 @@ class Excerpt // if we are going to snip too much... if ($textlength - $startPos < $relLength) { - $startPos -= ($textlength - $startPos) / 2; + $startPos -= (int) round(($textlength - $startPos) / 2); } - $relText = mb_substr($fulltext, (int) $startPos, (int) $relLength); + $relText = mb_substr($fulltext, $startPos, $relLength); // check to ensure we don't snip the last word if that's the match if ($startPos + $relLength < $textlength) { diff --git a/src/Storage/Query/Query.php b/src/Storage/Query/Query.php index 7096e4df..a1a15c37 100644 --- a/src/Storage/Query/Query.php +++ b/src/Storage/Query/Query.php @@ -57,7 +57,7 @@ class Query } /** - * @return bool|QueryResultset|null + * @return QueryResultset|Content|null */ public function getContentByScope(string $scopeName, string $textQuery, array $parameters = []) { @@ -78,17 +78,7 @@ class Query */ public function getContentForTwig(string $textQuery, array $parameters = []) { - if (func_num_args() === 3) { - $whereparameters = func_get_arg(2); - if (is_array($whereparameters) && ! empty($whereparameters)) { - $parameters = array_merge($parameters, $whereparameters); - } - } - $results = $this->getContentByScope('frontend', $textQuery, $parameters); - if ($results instanceof QueryResultset) { - $results = $results->get(); - } return $this->recordsView->createView($results); } diff --git a/src/Storage/Query/SelectQuery.php b/src/Storage/Query/SelectQuery.php index aa05cf01..42e4b1a5 100644 --- a/src/Storage/Query/SelectQuery.php +++ b/src/Storage/Query/SelectQuery.php @@ -244,12 +244,10 @@ class SelectQuery implements ContentQueryInterface /** * Turns single fetch mode on or off. - * - * @param bool $value */ - public function setSingleFetchMode($value): void + public function setSingleFetchMode(bool $value): void { - $this->singleFetchMode = (bool) $value; + $this->singleFetchMode = $value; } /** diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 2f9aafa7..b5301d1b 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -24,7 +24,6 @@ class AppExtension extends AbstractExtension new TwigFilter('unique', [$this, 'unique']), new TwigFilter('localedatetime', [$this, 'dummy']), new TwigFilter('showimage', [$this, 'dummy']), - new TwigFilter('excerpt', [$this, 'excerpt']), new TwigFilter('ucwords', [$this, 'ucwords']), ]; } diff --git a/src/Twig/ArrayExtension.php b/src/Twig/ArrayExtension.php index 4cb7562d..c7510ec7 100644 --- a/src/Twig/ArrayExtension.php +++ b/src/Twig/ArrayExtension.php @@ -92,13 +92,6 @@ final class ArrayExtension extends AbstractExtension */ public function order(array $array, string $on, ?string $onSecondary = null): array { - // If we don't get a string, we can't determine a sort order. - if (! is_string($on)) { - throw new \InvalidArgumentException(sprintf('Second parameter passed to %s must be a string, %s given', __METHOD__, gettype($on))); - } - if (! (is_string($onSecondary) || $onSecondary === null)) { - throw new \InvalidArgumentException(sprintf('Third parameter passed to %s must be a string, %s given', __METHOD__, gettype($onSecondary))); - } // Set the 'orderOn' and 'orderAscending', taking into account things like '-datepublish'. [$this->orderOn, $this->orderAscending] = $this->getSortOrder($on); diff --git a/src/Twig/ContentHelperExtension.php b/src/Twig/ContentHelperExtension.php index 1b64291b..bcb2a0c4 100644 --- a/src/Twig/ContentHelperExtension.php +++ b/src/Twig/ContentHelperExtension.php @@ -57,7 +57,6 @@ class ContentHelperExtension extends AbstractExtension new TwigFunction('sidebarmenu', [$this, 'sidebarmenu']), new TwigFunction('jsonlabels', [$this, 'jsonlabels']), new TwigFunction('jsonrecords', [$this, 'jsonrecords']), - new TwigFunction('fieldfactory', [$this, 'fieldfactory']), new TwigFunction('selectoptionsfromarray', [$this, 'selectoptionsfromarray']), new TwigFunction('taxonomyoptions', [$this, 'taxonomyoptions']), new TwigFunction('taxonomyvalues', [$this, 'taxonomyvalues']), diff --git a/src/Twig/RecordExtension.php b/src/Twig/RecordExtension.php index be932b80..6abe4e32 100644 --- a/src/Twig/RecordExtension.php +++ b/src/Twig/RecordExtension.php @@ -52,10 +52,10 @@ class RecordExtension extends AbstractExtension return $input; } - public function excerpt(string $text, int $length = 100): string + public static function excerpt(string $text, int $length = 100): string { $excerpter = new Excerpt($text); - return $excerpter->getExcerpt((int) $length); + return $excerpter->getExcerpt($length); } } diff --git a/src/Twig/TwigRecordsView.php b/src/Twig/TwigRecordsView.php index eb94d470..db4f7aa8 100644 --- a/src/Twig/TwigRecordsView.php +++ b/src/Twig/TwigRecordsView.php @@ -69,7 +69,7 @@ class TwigRecordsView if (is_array($values)) { foreach ($values as $field => $value) { /* Get type of a field based on $record->getContenttype() and $field */ - $type = ''; + $type = []; $boltType = ''; $record->set($field, $this->transform($value, $boltType, $type)); }