Merge pull request #1635 from ArthurHoaro/feature/phpcs

This commit is contained in:
ArthurHoaro 2020-11-10 10:46:04 +01:00 committed by GitHub
commit 302662797c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 480 additions and 386 deletions

View file

@ -49,6 +49,10 @@ cache:
directories: directories:
- $HOME/.composer/cache - $HOME/.composer/cache
before_install:
# Disable xdebug: it significantly speed up tests and linter, and we don't use coverage yet
- phpenv config-rm xdebug.ini || echo 'No xdebug config.'
install: install:
# install/update composer and php dependencies # install/update composer and php dependencies
- composer config --unset platform && composer config platform.php $TRAVIS_PHP_VERSION - composer config --unset platform && composer config platform.php $TRAVIS_PHP_VERSION
@ -60,4 +64,5 @@ before_script:
script: script:
- make clean - make clean
- make check_permissions - make check_permissions
- make code_sniffer
- make all_tests - make all_tests

View file

@ -27,10 +27,6 @@ PHPCS := $(BIN)/phpcs
code_sniffer: code_sniffer:
@$(PHPCS) @$(PHPCS)
### - errors filtered by coding standard: PEAR, PSR1, PSR2, Zend...
PHPCS_%:
@$(PHPCS) --report-full --report-width=200 --standard=$*
### - errors by Git author ### - errors by Git author
code_sniffer_blame: code_sniffer_blame:
@$(PHPCS) --report-gitblame @$(PHPCS) --report-gitblame

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli; namespace Shaarli;
use DateTime; use DateTime;
@ -31,27 +32,27 @@ class History
/** /**
* @var string Action key: a new link has been created. * @var string Action key: a new link has been created.
*/ */
const CREATED = 'CREATED'; public const CREATED = 'CREATED';
/** /**
* @var string Action key: a link has been updated. * @var string Action key: a link has been updated.
*/ */
const UPDATED = 'UPDATED'; public const UPDATED = 'UPDATED';
/** /**
* @var string Action key: a link has been deleted. * @var string Action key: a link has been deleted.
*/ */
const DELETED = 'DELETED'; public const DELETED = 'DELETED';
/** /**
* @var string Action key: settings have been updated. * @var string Action key: settings have been updated.
*/ */
const SETTINGS = 'SETTINGS'; public const SETTINGS = 'SETTINGS';
/** /**
* @var string Action key: a bulk import has been processed. * @var string Action key: a bulk import has been processed.
*/ */
const IMPORT = 'IMPORT'; public const IMPORT = 'IMPORT';
/** /**
* @var string History file path. * @var string History file path.

View file

@ -41,7 +41,7 @@ class Languages
/** /**
* Core translations domain * Core translations domain
*/ */
const DEFAULT_DOMAIN = 'shaarli'; public const DEFAULT_DOMAIN = 'shaarli';
/** /**
* @var TranslatorInterface * @var TranslatorInterface
@ -76,7 +76,8 @@ public function __construct($language, $conf)
$this->language = $confLanguage; $this->language = $confLanguage;
} }
if (! extension_loaded('gettext') if (
! extension_loaded('gettext')
|| in_array($this->conf->get('translation.mode', 'auto'), ['auto', 'php']) || in_array($this->conf->get('translation.mode', 'auto'), ['auto', 'php'])
) { ) {
$this->initPhpTranslator(); $this->initPhpTranslator();
@ -121,7 +122,9 @@ protected function initPhpTranslator()
$translations = new Translations(); $translations = new Translations();
// Core translations // Core translations
try { try {
$translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po'); $translations = $translations->addFromPoFile(
'inc/languages/' . $this->language . '/LC_MESSAGES/shaarli.po'
);
$translations->setDomain('shaarli'); $translations->setDomain('shaarli');
$this->translator->loadTranslations($translations); $this->translator->loadTranslations($translations);
} catch (\InvalidArgumentException $e) { } catch (\InvalidArgumentException $e) {

View file

@ -13,7 +13,7 @@
*/ */
class Thumbnailer class Thumbnailer
{ {
const COMMON_MEDIA_DOMAINS = [ protected const COMMON_MEDIA_DOMAINS = [
'imgur.com', 'imgur.com',
'flickr.com', 'flickr.com',
'youtube.com', 'youtube.com',
@ -31,9 +31,9 @@ class Thumbnailer
'deviantart.com', 'deviantart.com',
]; ];
const MODE_ALL = 'all'; public const MODE_ALL = 'all';
const MODE_COMMON = 'common'; public const MODE_COMMON = 'common';
const MODE_NONE = 'none'; public const MODE_NONE = 'none';
/** /**
* @var WebThumbnailer instance. * @var WebThumbnailer instance.
@ -81,7 +81,8 @@ public function __construct($conf)
*/ */
public function get($url) public function get($url)
{ {
if ($this->conf->get('thumbnails.mode') === self::MODE_COMMON if (
$this->conf->get('thumbnails.mode') === self::MODE_COMMON
&& ! $this->isCommonMediaOrImage($url) && ! $this->isCommonMediaOrImage($url)
) { ) {
return false; return false;

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Generates a list of available timezone continents and cities. * Generates a list of available timezone continents and cities.
* *

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Shaarli utilities * Shaarli utilities
*/ */
@ -102,7 +103,7 @@ function escape($input)
} }
if (is_array($input)) { if (is_array($input)) {
$out = array(); $out = [];
foreach ($input as $key => $value) { foreach ($input as $key => $value) {
$out[escape($key)] = escape($value); $out[escape($key)] = escape($value);
} }
@ -163,7 +164,7 @@ function checkDateFormat($format, $string)
* *
* @return string $referer - final referer. * @return string $referer - final referer.
*/ */
function generateLocation($referer, $host, $loopTerms = array()) function generateLocation($referer, $host, $loopTerms = [])
{ {
$finalReferer = './?'; $finalReferer = './?';
@ -196,7 +197,7 @@ function generateLocation($referer, $host, $loopTerms = array())
function autoLocale($headerLocale) function autoLocale($headerLocale)
{ {
// Default if browser does not send HTTP_ACCEPT_LANGUAGE // Default if browser does not send HTTP_ACCEPT_LANGUAGE
$locales = array('en_US', 'en_US.utf8', 'en_US.UTF-8'); $locales = ['en_US', 'en_US.utf8', 'en_US.UTF-8'];
if (! empty($headerLocale)) { if (! empty($headerLocale)) {
if (preg_match_all('/([a-z]{2,3})[-_]?([a-z]{2})?,?/i', $headerLocale, $matches, PREG_SET_ORDER)) { if (preg_match_all('/([a-z]{2,3})[-_]?([a-z]{2})?,?/i', $headerLocale, $matches, PREG_SET_ORDER)) {
$attempts = []; $attempts = [];
@ -381,8 +382,10 @@ function return_bytes($val)
switch ($last) { switch ($last) {
case 'g': case 'g':
$val *= 1024; $val *= 1024;
// do no break in order 1024^2 for each unit
case 'm': case 'm':
$val *= 1024; $val *= 1024;
// do no break in order 1024^2 for each unit
case 'k': case 'k':
$val *= 1024; $val *= 1024;
} }
@ -482,7 +485,9 @@ function alphabetical_sort(&$data, $reverse = false, $byKeys = false)
*/ */
function t($text, $nText = '', $nb = 1, $domain = 'shaarli', $variables = [], $fixCase = false) function t($text, $nText = '', $nb = 1, $domain = 'shaarli', $variables = [], $fixCase = false)
{ {
$postFunction = $fixCase ? 'ucfirst' : function ($input) { return $input; }; $postFunction = $fixCase ? 'ucfirst' : function ($input) {
return $input;
};
return $postFunction(dn__($domain, $text, $nText, $nb, $variables)); return $postFunction(dn__($domain, $text, $nText, $nb, $variables));
} }
@ -494,4 +499,3 @@ function exception2text(Throwable $e): string
{ {
return $e->getMessage() . PHP_EOL . $e->getFile() . $e->getLine() . PHP_EOL . $e->getTraceAsString(); return $e->getMessage() . PHP_EOL . $e->getFile() . $e->getLine() . PHP_EOL . $e->getTraceAsString();
} }

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Api; namespace Shaarli\Api;
use malkusch\lock\mutex\FlockMutex; use malkusch\lock\mutex\FlockMutex;
@ -108,7 +109,8 @@ protected function checkRequest($request)
*/ */
protected function checkToken($request) protected function checkToken($request)
{ {
if (!$request->hasHeader('Authorization') if (
!$request->hasHeader('Authorization')
&& !isset($this->container->environment['REDIRECT_HTTP_AUTHORIZATION']) && !isset($this->container->environment['REDIRECT_HTTP_AUTHORIZATION'])
) { ) {
throw new ApiAuthorizationException('JWT token not provided'); throw new ApiAuthorizationException('JWT token not provided');

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Api; namespace Shaarli\Api;
use Shaarli\Api\Exceptions\ApiAuthorizationException; use Shaarli\Api\Exceptions\ApiAuthorizationException;
@ -42,7 +43,8 @@ public static function validateJwtToken($token, $secret)
throw new ApiAuthorizationException('Invalid JWT payload'); throw new ApiAuthorizationException('Invalid JWT payload');
} }
if (empty($payload->iat) if (
empty($payload->iat)
|| $payload->iat > time() || $payload->iat > time()
|| time() - $payload->iat > ApiMiddleware::$TOKEN_DURATION || time() - $payload->iat > ApiMiddleware::$TOKEN_DURATION
) { ) {

View file

@ -1,6 +1,5 @@
<?php <?php
namespace Shaarli\Api\Controllers; namespace Shaarli\Api\Controllers;
use Shaarli\Api\Exceptions\ApiBadParametersException; use Shaarli\Api\Exceptions\ApiBadParametersException;

View file

@ -29,13 +29,13 @@ public function getInfo($request, $response)
$info = [ $info = [
'global_counter' => $this->bookmarkService->count(), 'global_counter' => $this->bookmarkService->count(),
'private_counter' => $this->bookmarkService->count(BookmarkFilter::$PRIVATE), 'private_counter' => $this->bookmarkService->count(BookmarkFilter::$PRIVATE),
'settings' => array( 'settings' => [
'title' => $this->conf->get('general.title', 'Shaarli'), 'title' => $this->conf->get('general.title', 'Shaarli'),
'header_link' => $this->conf->get('general.header_link', '?'), 'header_link' => $this->conf->get('general.header_link', '?'),
'timezone' => $this->conf->get('general.timezone', 'UTC'), 'timezone' => $this->conf->get('general.timezone', 'UTC'),
'enabled_plugins' => $this->conf->get('general.enabled_plugins', []), 'enabled_plugins' => $this->conf->get('general.enabled_plugins', []),
'default_private_links' => $this->conf->get('privacy.default_private_links', false), 'default_private_links' => $this->conf->get('privacy.default_private_links', false),
), ],
]; ];
return $response->withJson($info, 200, $this->jsonStyle); return $response->withJson($info, 200, $this->jsonStyle);

View file

@ -119,7 +119,8 @@ public function postLink($request, $response)
$data = (array) ($request->getParsedBody() ?? []); $data = (array) ($request->getParsedBody() ?? []);
$bookmark = ApiUtils::buildBookmarkFromRequest($data, $this->conf->get('privacy.default_private_links')); $bookmark = ApiUtils::buildBookmarkFromRequest($data, $this->conf->get('privacy.default_private_links'));
// duplicate by URL, return 409 Conflict // duplicate by URL, return 409 Conflict
if (! empty($bookmark->getUrl()) if (
! empty($bookmark->getUrl())
&& ! empty($dup = $this->bookmarkService->findByUrl($bookmark->getUrl())) && ! empty($dup = $this->bookmarkService->findByUrl($bookmark->getUrl()))
) { ) {
return $response->withJson( return $response->withJson(
@ -159,7 +160,8 @@ public function putLink($request, $response, $args)
$requestBookmark = ApiUtils::buildBookmarkFromRequest($data, $this->conf->get('privacy.default_private_links')); $requestBookmark = ApiUtils::buildBookmarkFromRequest($data, $this->conf->get('privacy.default_private_links'));
// duplicate URL on a different link, return 409 Conflict // duplicate URL on a different link, return 409 Conflict
if (! empty($requestBookmark->getUrl()) if (
! empty($requestBookmark->getUrl())
&& ! empty($dup = $this->bookmarkService->findByUrl($requestBookmark->getUrl())) && ! empty($dup = $this->bookmarkService->findByUrl($requestBookmark->getUrl()))
&& $dup->getId() != $id && $dup->getId() != $id
) { ) {

View file

@ -19,7 +19,7 @@
class Bookmark class Bookmark
{ {
/** @var string Date format used in string (former ID format) */ /** @var string Date format used in string (former ID format) */
const LINK_DATE_FORMAT = 'Ymd_His'; public const LINK_DATE_FORMAT = 'Ymd_His';
/** @var int Bookmark ID */ /** @var int Bookmark ID */
protected $id; protected $id;
@ -106,7 +106,8 @@ public function fromArray(array $data, string $tagsSeparator = ' '): Bookmark
*/ */
public function validate(): void public function validate(): void
{ {
if ($this->id === null if (
$this->id === null
|| ! is_int($this->id) || ! is_int($this->id)
|| empty($this->shortUrl) || empty($this->shortUrl)
|| empty($this->created) || empty($this->created)

View file

@ -72,7 +72,8 @@ public function count()
*/ */
public function offsetSet($offset, $value) public function offsetSet($offset, $value)
{ {
if (! $value instanceof Bookmark if (
! $value instanceof Bookmark
|| $value->getId() === null || empty($value->getUrl()) || $value->getId() === null || empty($value->getUrl())
|| ($offset !== null && ! is_int($offset)) || ! is_int($value->getId()) || ($offset !== null && ! is_int($offset)) || ! is_int($value->getId())
|| $offset !== null && $offset !== $value->getId() || $offset !== null && $offset !== $value->getId()
@ -222,7 +223,8 @@ public function getNextId(): int
*/ */
public function getByUrl(string $url): ?Bookmark public function getByUrl(string $url): ?Bookmark
{ {
if (! empty($url) if (
! empty($url)
&& isset($this->urls[$url]) && isset($this->urls[$url])
&& isset($this->bookmarks[$this->urls[$url]]) && isset($this->bookmarks[$this->urls[$url]])
) { ) {

View file

@ -102,7 +102,8 @@ public function findByHash(string $hash, string $privateKey = null): Bookmark
$bookmark = $this->bookmarkFilter->filter(BookmarkFilter::$FILTER_HASH, $hash); $bookmark = $this->bookmarkFilter->filter(BookmarkFilter::$FILTER_HASH, $hash);
// PHP 7.3 introduced array_key_first() to avoid this hack // PHP 7.3 introduced array_key_first() to avoid this hack
$first = reset($bookmark); $first = reset($bookmark);
if (!$this->isLoggedIn if (
!$this->isLoggedIn
&& $first->isPrivate() && $first->isPrivate()
&& (empty($privateKey) || $privateKey !== $first->getAdditionalContentEntry('private_key')) && (empty($privateKey) || $privateKey !== $first->getAdditionalContentEntry('private_key'))
) { ) {
@ -165,7 +166,8 @@ public function get(int $id, string $visibility = null): Bookmark
} }
$bookmark = $this->bookmarks[$id]; $bookmark = $this->bookmarks[$id];
if (($bookmark->isPrivate() && $visibility != 'all' && $visibility != 'private') if (
($bookmark->isPrivate() && $visibility != 'all' && $visibility != 'private')
|| (! $bookmark->isPrivate() && $visibility != 'all' && $visibility != 'public') || (! $bookmark->isPrivate() && $visibility != 'all' && $visibility != 'public')
) { ) {
throw new Exception('Unauthorized'); throw new Exception('Unauthorized');
@ -265,7 +267,8 @@ public function exists(int $id, string $visibility = null): bool
} }
$bookmark = $this->bookmarks[$id]; $bookmark = $this->bookmarks[$id];
if (($bookmark->isPrivate() && $visibility != 'all' && $visibility != 'private') if (
($bookmark->isPrivate() && $visibility != 'all' && $visibility != 'private')
|| (! $bookmark->isPrivate() && $visibility != 'all' && $visibility != 'public') || (! $bookmark->isPrivate() && $visibility != 'all' && $visibility != 'public')
) { ) {
return false; return false;
@ -307,7 +310,8 @@ public function bookmarksCountPerTag(array $filteringTags = [], string $visibili
$caseMapping = []; $caseMapping = [];
foreach ($bookmarks as $bookmark) { foreach ($bookmarks as $bookmark) {
foreach ($bookmark->getTags() as $tag) { foreach ($bookmark->getTags() as $tag) {
if (empty($tag) if (
empty($tag)
|| (! $this->isLoggedIn && startsWith($tag, '.')) || (! $this->isLoggedIn && startsWith($tag, '.'))
|| $tag === BookmarkMarkdownFormatter::NO_MD_TAG || $tag === BookmarkMarkdownFormatter::NO_MD_TAG
|| in_array($tag, $filteringTags, true) || in_array($tag, $filteringTags, true)
@ -405,14 +409,14 @@ protected function migrate(): void
false false
); );
$updater = new LegacyUpdater( $updater = new LegacyUpdater(
UpdaterUtils::read_updates_file($this->conf->get('resource.updates')), UpdaterUtils::readUpdatesFile($this->conf->get('resource.updates')),
$bookmarkDb, $bookmarkDb,
$this->conf, $this->conf,
true true
); );
$newUpdates = $updater->update(); $newUpdates = $updater->update();
if (! empty($newUpdates)) { if (! empty($newUpdates)) {
UpdaterUtils::write_updates_file( UpdaterUtils::writeUpdatesFile(
$this->conf->get('resource.updates'), $this->conf->get('resource.updates'),
$updater->getDoneUpdates() $updater->getDoneUpdates()
); );

View file

@ -150,7 +150,7 @@ private function noFilter(string $visibility = 'all')
return $this->bookmarks; return $this->bookmarks;
} }
$out = array(); $out = [];
foreach ($this->bookmarks as $key => $value) { foreach ($this->bookmarks as $key => $value) {
if ($value->isPrivate() && $visibility === 'private') { if ($value->isPrivate() && $visibility === 'private') {
$out[$key] = $value; $out[$key] = $value;
@ -395,7 +395,7 @@ public function filterTags($tags, bool $casesensitive = false, string $visibilit
$search = $link->getTagsString($tagsSeparator); $search = $link->getTagsString($tagsSeparator);
if (strlen(trim($link->getDescription())) && strpos($link->getDescription(), '#') !== false) { if (strlen(trim($link->getDescription())) && strpos($link->getDescription(), '#') !== false) {
// description given and at least one possible tag found // description given and at least one possible tag found
$descTags = array(); $descTags = [];
// find all tags in the form of #tag in the description // find all tags in the form of #tag in the description
preg_match_all( preg_match_all(
'/(?<![' . self::$HASHTAG_CHARS . '])#([' . self::$HASHTAG_CHARS . ']+?)\b/sm', '/(?<![' . self::$HASHTAG_CHARS . '])#([' . self::$HASHTAG_CHARS . ']+?)\b/sm',

View file

@ -13,6 +13,9 @@
* To prevent data corruption, it does not overwrite existing bookmarks, * To prevent data corruption, it does not overwrite existing bookmarks,
* even though there should not be any. * even though there should not be any.
* *
* We disable this because otherwise it creates indentation issues, and heredoc is not supported by PHP gettext.
* @phpcs:disable Generic.Files.LineLength.TooLong
*
* @package Shaarli\Bookmark * @package Shaarli\Bookmark
*/ */
class BookmarkInitializer class BookmarkInitializer

View file

@ -74,7 +74,8 @@ function html_extract_tag($tag, $html)
// New regex to keep this readable... more or less. // New regex to keep this readable... more or less.
$ogRegexReverse = '#<meta[^>]+content=(["\'])([^\1]*?)\1[^>]+(?:' . $properties . ')=(?:' . $orCondition . ').*?>#'; $ogRegexReverse = '#<meta[^>]+content=(["\'])([^\1]*?)\1[^>]+(?:' . $properties . ')=(?:' . $orCondition . ').*?>#';
if (preg_match($ogRegex, $html, $matches) > 0 if (
preg_match($ogRegex, $html, $matches) > 0
|| preg_match($ogRegexReverse, $html, $matches) > 0 || preg_match($ogRegexReverse, $html, $matches) > 0
) { ) {
return $matches[2]; return $matches[2];

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Bookmark\Exception; namespace Shaarli\Bookmark\Exception;
use Exception; use Exception;

View file

@ -1,7 +1,7 @@
<?php <?php
namespace Shaarli\Bookmark\Exception; namespace Shaarli\Bookmark\Exception;
class EmptyDataStoreException extends \Exception
class EmptyDataStoreException extends \Exception {} {
}

View file

@ -1,9 +1,7 @@
<?php <?php
namespace Shaarli\Bookmark\Exception; namespace Shaarli\Bookmark\Exception;
class NotWritableDataStoreException extends \Exception class NotWritableDataStoreException extends \Exception
{ {
/** /**

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Config; namespace Shaarli\Config;
/** /**

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Config; namespace Shaarli\Config;
use Shaarli\Config\Exception\MissingFieldConfigException; use Shaarli\Config\Exception\MissingFieldConfigException;
@ -20,7 +21,7 @@ class ConfigManager
*/ */
protected static $NOT_FOUND = 'NOT_FOUND'; protected static $NOT_FOUND = 'NOT_FOUND';
public static $DEFAULT_PLUGINS = array('qrcode'); public static $DEFAULT_PLUGINS = ['qrcode'];
/** /**
* @var string Config folder. * @var string Config folder.
@ -213,7 +214,7 @@ public function exists($setting)
public function write($isLoggedIn) public function write($isLoggedIn)
{ {
// These fields are required in configuration. // These fields are required in configuration.
$mandatoryFields = array( $mandatoryFields = [
'credentials.login', 'credentials.login',
'credentials.hash', 'credentials.hash',
'credentials.salt', 'credentials.salt',
@ -222,7 +223,7 @@ public function write($isLoggedIn)
'general.title', 'general.title',
'general.header_link', 'general.header_link',
'privacy.default_private_links', 'privacy.default_private_links',
); ];
// Only logged in user can alter config. // Only logged in user can alter config.
if (is_file($this->getConfigFileExt()) && !$isLoggedIn) { if (is_file($this->getConfigFileExt()) && !$isLoggedIn) {
@ -392,7 +393,7 @@ protected function setDefaultValues()
$this->setEmpty('translation.mode', 'php'); $this->setEmpty('translation.mode', 'php');
$this->setEmpty('translation.extensions', []); $this->setEmpty('translation.extensions', []);
$this->setEmpty('plugins', array()); $this->setEmpty('plugins', []);
$this->setEmpty('formatter', 'markdown'); $this->setEmpty('formatter', 'markdown');
} }

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Config; namespace Shaarli\Config;
/** /**
@ -12,7 +13,7 @@ class ConfigPhp implements ConfigIO
/** /**
* @var array List of config key without group. * @var array List of config key without group.
*/ */
public static $ROOT_KEYS = array( public static $ROOT_KEYS = [
'login', 'login',
'hash', 'hash',
'salt', 'salt',
@ -22,7 +23,7 @@ class ConfigPhp implements ConfigIO
'redirector', 'redirector',
'disablesessionprotection', 'disablesessionprotection',
'privateLinkByDefault', 'privateLinkByDefault',
); ];
/** /**
* Map legacy config keys with the new ones. * Map legacy config keys with the new ones.
@ -31,7 +32,7 @@ class ConfigPhp implements ConfigIO
* *
* @var array current key => legacy key. * @var array current key => legacy key.
*/ */
public static $LEGACY_KEYS_MAPPING = array( public static $LEGACY_KEYS_MAPPING = [
'credentials.login' => 'login', 'credentials.login' => 'login',
'credentials.hash' => 'hash', 'credentials.hash' => 'hash',
'credentials.salt' => 'salt', 'credentials.salt' => 'salt',
@ -68,7 +69,7 @@ class ConfigPhp implements ConfigIO
'privacy.hide_public_links' => 'config.HIDE_PUBLIC_LINKS', 'privacy.hide_public_links' => 'config.HIDE_PUBLIC_LINKS',
'privacy.hide_timestamps' => 'config.HIDE_TIMESTAMPS', 'privacy.hide_timestamps' => 'config.HIDE_TIMESTAMPS',
'security.open_shaarli' => 'config.OPEN_SHAARLI', 'security.open_shaarli' => 'config.OPEN_SHAARLI',
); ];
/** /**
* @inheritdoc * @inheritdoc
@ -76,12 +77,12 @@ class ConfigPhp implements ConfigIO
public function read($filepath) public function read($filepath)
{ {
if (! file_exists($filepath) || ! is_readable($filepath)) { if (! file_exists($filepath) || ! is_readable($filepath)) {
return array(); return [];
} }
include $filepath; include $filepath;
$out = array(); $out = [];
foreach (self::$ROOT_KEYS as $key) { foreach (self::$ROOT_KEYS as $key) {
$out[$key] = isset($GLOBALS[$key]) ? $GLOBALS[$key] : ''; $out[$key] = isset($GLOBALS[$key]) ? $GLOBALS[$key] : '';
} }
@ -121,7 +122,8 @@ public function write($filepath, $conf)
} }
} }
if (!file_put_contents($filepath, $configStr) if (
!file_put_contents($filepath, $configStr)
|| strcmp(file_get_contents($filepath), $configStr) != 0 || strcmp(file_get_contents($filepath), $configStr) != 0
) { ) {
throw new \Shaarli\Exceptions\IOException( throw new \Shaarli\Exceptions\IOException(

View file

@ -39,8 +39,8 @@ function ($value, string $key) use ($directories) {
throw new PluginConfigOrderException(); throw new PluginConfigOrderException();
} }
$plugins = array(); $plugins = [];
$newEnabledPlugins = array(); $newEnabledPlugins = [];
foreach ($formData as $key => $data) { foreach ($formData as $key => $data) {
if (startsWith($key, 'order')) { if (startsWith($key, 'order')) {
continue; continue;
@ -62,7 +62,7 @@ function ($value, string $key) use ($directories) {
throw new PluginConfigOrderException(); throw new PluginConfigOrderException();
} }
$finalPlugins = array(); $finalPlugins = [];
// Make plugins order continuous. // Make plugins order continuous.
foreach ($plugins as $plugin) { foreach ($plugins as $plugin) {
$finalPlugins[] = $plugin; $finalPlugins[] = $plugin;
@ -81,7 +81,7 @@ function ($value, string $key) use ($directories) {
*/ */
function validate_plugin_order($formData) function validate_plugin_order($formData)
{ {
$orders = array(); $orders = [];
foreach ($formData as $key => $value) { foreach ($formData as $key => $value) {
// No duplicate order allowed. // No duplicate order allowed.
if (in_array($value, $orders, true)) { if (in_array($value, $orders, true)) {

View file

@ -1,6 +1,5 @@
<?php <?php
namespace Shaarli\Config\Exception; namespace Shaarli\Config\Exception;
/** /**

View file

@ -1,6 +1,5 @@
<?php <?php
namespace Shaarli\Config\Exception; namespace Shaarli\Config\Exception;
/** /**

View file

@ -158,7 +158,7 @@ public function build(): ShaarliContainer
$container['updater'] = function (ShaarliContainer $container): Updater { $container['updater'] = function (ShaarliContainer $container): Updater {
return new Updater( return new Updater(
UpdaterUtils::read_updates_file($container->conf->get('resource.updates')), UpdaterUtils::readUpdatesFile($container->conf->get('resource.updates')),
$container->bookmarkService, $container->bookmarkService,
$container->conf, $container->conf,
$container->loginManager->isLoggedIn() $container->loginManager->isLoggedIn()

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Exceptions; namespace Shaarli\Exceptions;
use Exception; use Exception;

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Feed; namespace Shaarli\Feed;
use DateTime; use DateTime;
@ -107,14 +108,14 @@ public function buildData(string $feedType, ?array $userInput)
$nblinksToDisplay = $this->getNbLinks(count($linksToDisplay), $userInput); $nblinksToDisplay = $this->getNbLinks(count($linksToDisplay), $userInput);
// Can't use array_keys() because $link is a LinkDB instance and not a real array. // Can't use array_keys() because $link is a LinkDB instance and not a real array.
$keys = array(); $keys = [];
foreach ($linksToDisplay as $key => $value) { foreach ($linksToDisplay as $key => $value) {
$keys[] = $key; $keys[] = $key;
} }
$pageaddr = escape(index_url($this->serverInfo)); $pageaddr = escape(index_url($this->serverInfo));
$this->formatter->addContextData('index_url', $pageaddr); $this->formatter->addContextData('index_url', $pageaddr);
$linkDisplayed = array(); $linkDisplayed = [];
for ($i = 0; $i < $nblinksToDisplay && $i < count($keys); $i++) { for ($i = 0; $i < $nblinksToDisplay && $i < count($keys); $i++) {
$linkDisplayed[$keys[$i]] = $this->buildItem($feedType, $linksToDisplay[$keys[$i]], $pageaddr); $linkDisplayed[$keys[$i]] = $this->buildItem($feedType, $linksToDisplay[$keys[$i]], $pageaddr);
} }

View file

@ -12,8 +12,8 @@
*/ */
class BookmarkDefaultFormatter extends BookmarkFormatter class BookmarkDefaultFormatter extends BookmarkFormatter
{ {
const SEARCH_HIGHLIGHT_OPEN = '|@@HIGHLIGHT'; protected const SEARCH_HIGHLIGHT_OPEN = '|@@HIGHLIGHT';
const SEARCH_HIGHLIGHT_CLOSE = 'HIGHLIGHT@@|'; protected const SEARCH_HIGHLIGHT_CLOSE = 'HIGHLIGHT@@|';
/** /**
* @inheritdoc * @inheritdoc

View file

@ -16,7 +16,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
/** /**
* When this tag is present in a bookmark, its description should not be processed with Markdown * When this tag is present in a bookmark, its description should not be processed with Markdown
*/ */
const NO_MD_TAG = 'nomarkdown'; public const NO_MD_TAG = 'nomarkdown';
/** @var \Parsedown instance */ /** @var \Parsedown instance */
protected $parsedown; protected $parsedown;
@ -178,14 +178,14 @@ protected function formatHashTags($description)
*/ */
protected function sanitizeHtml($description) protected function sanitizeHtml($description)
{ {
$escapeTags = array( $escapeTags = [
'script', 'script',
'style', 'style',
'link', 'link',
'iframe', 'iframe',
'frameset', 'frameset',
'frame', 'frame',
); ];
foreach ($escapeTags as $tag) { foreach ($escapeTags as $tag) {
$description = preg_replace_callback( $description = preg_replace_callback(
'#<\s*' . $tag . '[^>]*>(.*</\s*' . $tag . '[^>]*>)?#is', '#<\s*' . $tag . '[^>]*>(.*</\s*' . $tag . '[^>]*>)?#is',

View file

@ -10,4 +10,6 @@
* *
* @package Shaarli\Formatter * @package Shaarli\Formatter
*/ */
class BookmarkRawFormatter extends BookmarkFormatter {} class BookmarkRawFormatter extends BookmarkFormatter
{
}

View file

@ -42,7 +42,8 @@ public function __invoke(Request $request, Response $response, callable $next):
$this->initBasePath($request); $this->initBasePath($request);
try { try {
if (!is_file($this->container->conf->getConfigFileExt()) if (
!is_file($this->container->conf->getConfigFileExt())
&& !in_array($next->getName(), ['displayInstall', 'saveInstall'], true) && !in_array($next->getName(), ['displayInstall', 'saveInstall'], true)
) { ) {
return $response->withRedirect($this->container->basePath . '/install'); return $response->withRedirect($this->container->basePath . '/install');
@ -86,7 +87,8 @@ protected function runUpdates(): void
*/ */
protected function checkOpenShaarli(Request $request, Response $response, callable $next): bool protected function checkOpenShaarli(Request $request, Response $response, callable $next): bool
{ {
if (// if the user isn't logged in if (
// if the user isn't logged in
!$this->container->loginManager->isLoggedIn() !$this->container->loginManager->isLoggedIn()
// and Shaarli doesn't have public content... // and Shaarli doesn't have public content...
&& $this->container->conf->get('privacy.hide_public_links') && $this->container->conf->get('privacy.hide_public_links')

View file

@ -51,7 +51,10 @@ public function index(Request $request, Response $response): Response
$this->assignView('languages', Languages::getAvailableLanguages()); $this->assignView('languages', Languages::getAvailableLanguages());
$this->assignView('gd_enabled', extension_loaded('gd')); $this->assignView('gd_enabled', extension_loaded('gd'));
$this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)); $this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
$this->assignView('pagetitle', t('Configure') .' - '. $this->container->conf->get('general.title', 'Shaarli')); $this->assignView(
'pagetitle',
t('Configure') . ' - ' . $this->container->conf->get('general.title', 'Shaarli')
);
return $response->write($this->render(TemplatePage::CONFIGURE)); return $response->write($this->render(TemplatePage::CONFIGURE));
} }
@ -95,12 +98,15 @@ public function save(Request $request, Response $response): Response
} }
$thumbnailsMode = extension_loaded('gd') ? $request->getParam('enableThumbnails') : Thumbnailer::MODE_NONE; $thumbnailsMode = extension_loaded('gd') ? $request->getParam('enableThumbnails') : Thumbnailer::MODE_NONE;
if ($thumbnailsMode !== Thumbnailer::MODE_NONE if (
$thumbnailsMode !== Thumbnailer::MODE_NONE
&& $thumbnailsMode !== $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) && $thumbnailsMode !== $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
) { ) {
$this->saveWarningMessage( $this->saveWarningMessage(
t('You have enabled or changed thumbnails mode.') . t('You have enabled or changed thumbnails mode.') .
'<a href="'. $this->container->basePath .'/admin/thumbnails">' . t('Please synchronize them.') .'</a>' '<a href="' . $this->container->basePath . '/admin/thumbnails">' .
t('Please synchronize them.') .
'</a>'
); );
} }
$this->container->conf->set('thumbnails.mode', $thumbnailsMode); $this->container->conf->set('thumbnails.mode', $thumbnailsMode);

View file

@ -72,7 +72,9 @@ public function clearCache(Request $request, Response $response): Response
$this->saveWarningMessage( $this->saveWarningMessage(
t('Thumbnails cache has been cleared.') . ' ' . t('Thumbnails cache has been cleared.') . ' ' .
'<a href="'. $this->container->basePath .'/admin/thumbnails">' . t('Please synchronize them.') .'</a>' '<a href="' . $this->container->basePath . '/admin/thumbnails">' .
t('Please synchronize them.') .
'</a>'
); );
} else { } else {
$folders = [ $folders = [

View file

@ -45,6 +45,4 @@ public function visibility(Request $request, Response $response, array $args): R
return $this->redirectFromReferer($request, $response, ['visibility']); return $this->redirectFromReferer($request, $response, ['visibility']);
} }
} }

View file

@ -118,7 +118,8 @@ public function save(Request $request, Response $response): Response
$this->container->conf->get('general.tags_separator', ' ') $this->container->conf->get('general.tags_separator', ' ')
); );
if ($this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE if (
$this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE
&& true !== $this->container->conf->get('general.enable_async_metadata', true) && true !== $this->container->conf->get('general.enable_async_metadata', true)
&& $bookmark->shouldUpdateThumbnail() && $bookmark->shouldUpdateThumbnail()
) { ) {
@ -148,7 +149,8 @@ public function save(Request $request, Response $response): Response
return $this->redirectFromReferer( return $this->redirectFromReferer(
$request, $request,
$response, $response,
['/admin/add-shaare', '/admin/shaare'], ['addlink', 'post', 'edit_link'], ['/admin/add-shaare', '/admin/shaare'],
['addlink', 'post', 'edit_link'],
$bookmark->getShortUrl() $bookmark->getShortUrl()
); );
} }
@ -194,7 +196,8 @@ protected function buildLinkDataFromUrl(Request $request, string $url): array
// If this is an HTTP(S) link, we try go get the page to extract // If this is an HTTP(S) link, we try go get the page to extract
// the title (otherwise we will to straight to the edit form.) // the title (otherwise we will to straight to the edit form.)
if (true !== $this->container->conf->get('general.enable_async_metadata', true) if (
true !== $this->container->conf->get('general.enable_async_metadata', true)
&& empty($title) && empty($title)
&& strpos(get_url_scheme($url) ?: '', 'http') !== false && strpos(get_url_scheme($url) ?: '', 'http') !== false
) { ) {

View file

@ -35,7 +35,8 @@ public function index(Request $request, Response $response): Response
$formatter->addContextData('base_path', $this->container->basePath); $formatter->addContextData('base_path', $this->container->basePath);
$searchTags = normalize_spaces($request->getParam('searchtags') ?? ''); $searchTags = normalize_spaces($request->getParam('searchtags') ?? '');
$searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));; $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));
;
// Filter bookmarks according search parameters. // Filter bookmarks according search parameters.
$visibility = $this->container->sessionManager->getSessionParameter('visibility'); $visibility = $this->container->sessionManager->getSessionParameter('visibility');
@ -185,7 +186,8 @@ protected function updateThumbnail(Bookmark $bookmark, bool $writeDatastore = tr
$bookmark->setThumbnail(null); $bookmark->setThumbnail(null);
// Requires an update, not async retrieval, thumbnails enabled // Requires an update, not async retrieval, thumbnails enabled
if ($bookmark->shouldUpdateThumbnail() if (
$bookmark->shouldUpdateThumbnail()
&& true !== $this->container->conf->get('general.enable_async_metadata', true) && true !== $this->container->conf->get('general.enable_async_metadata', true)
&& $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE && $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE
) { ) {

View file

@ -39,7 +39,8 @@ public function index(Request $request, Response $response): Response
// Before installation, we'll make sure that permissions are set properly, and sessions are working. // Before installation, we'll make sure that permissions are set properly, and sessions are working.
$this->checkPermissions(); $this->checkPermissions();
if (static::SESSION_TEST_VALUE if (
static::SESSION_TEST_VALUE
!== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY) !== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY)
) { ) {
$this->container->sessionManager->setSessionParameter(static::SESSION_TEST_KEY, static::SESSION_TEST_VALUE); $this->container->sessionManager->setSessionParameter(static::SESSION_TEST_KEY, static::SESSION_TEST_VALUE);
@ -75,7 +76,8 @@ public function sessionTest(Request $request, Response $response): Response
// This part makes sure sessions works correctly. // This part makes sure sessions works correctly.
// (Because on some hosts, session.save_path may not be set correctly, // (Because on some hosts, session.save_path may not be set correctly,
// or we may not have write access to it.) // or we may not have write access to it.)
if (static::SESSION_TEST_VALUE if (
static::SESSION_TEST_VALUE
!== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY) !== $this->container->sessionManager->getSessionParameter(static::SESSION_TEST_KEY)
) { ) {
// Step 2: Check if data in session is correct. // Step 2: Check if data in session is correct.
@ -104,7 +106,8 @@ public function sessionTest(Request $request, Response $response): Response
public function save(Request $request, Response $response): Response public function save(Request $request, Response $response): Response
{ {
$timezone = 'UTC'; $timezone = 'UTC';
if (!empty($request->getParam('continent')) if (
!empty($request->getParam('continent'))
&& !empty($request->getParam('city')) && !empty($request->getParam('city'))
&& isTimeZoneValid($request->getParam('continent'), $request->getParam('city')) && isTimeZoneValid($request->getParam('continent'), $request->getParam('city'))
) { ) {

View file

@ -64,7 +64,8 @@ public function login(Request $request, Response $response): Response
return $this->redirect($response, '/'); return $this->redirect($response, '/');
} }
if (!$this->container->loginManager->checkCredentials( if (
!$this->container->loginManager->checkCredentials(
client_ip_id($this->container->environment), client_ip_id($this->container->environment),
$request->getParam('login'), $request->getParam('login'),
$request->getParam('password') $request->getParam('password')
@ -101,7 +102,8 @@ public function login(Request $request, Response $response): Response
*/ */
protected function checkLoginState(): bool protected function checkLoginState(): bool
{ {
if ($this->container->loginManager->isLoggedIn() if (
$this->container->loginManager->isLoggedIn()
|| $this->container->conf->get('security.open_shaarli', false) || $this->container->conf->get('security.open_shaarli', false)
) { ) {
throw new CantLoginException(); throw new CantLoginException();

View file

@ -144,7 +144,8 @@ protected function redirectFromReferer(
if (null !== $referer) { if (null !== $referer) {
$currentUrl = parse_url($referer); $currentUrl = parse_url($referer);
// If the referer is not related to Shaarli instance, redirect to default // If the referer is not related to Shaarli instance, redirect to default
if (isset($currentUrl['host']) if (
isset($currentUrl['host'])
&& strpos(index_url($this->container->environment), $currentUrl['host']) === false && strpos(index_url($this->container->environment), $currentUrl['host']) === false
) { ) {
return $response->withRedirect($defaultPath); return $response->withRedirect($defaultPath);

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Helper; namespace Shaarli\Helper;
use Exception; use Exception;
@ -16,7 +17,7 @@ class ApplicationUtils
public static $GITHUB_URL = 'https://github.com/shaarli/Shaarli'; public static $GITHUB_URL = 'https://github.com/shaarli/Shaarli';
public static $GIT_RAW_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli'; public static $GIT_RAW_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli';
public static $GIT_BRANCHES = array('latest', 'stable'); public static $GIT_BRANCHES = ['latest', 'stable'];
private static $VERSION_START_TAG = '<?php /* '; private static $VERSION_START_TAG = '<?php /* ';
private static $VERSION_END_TAG = ' */ ?>'; private static $VERSION_END_TAG = ' */ ?>';
@ -64,8 +65,8 @@ public static function getVersion($remote, $timeout = 2)
} }
return str_replace( return str_replace(
array(self::$VERSION_START_TAG, self::$VERSION_END_TAG, PHP_EOL), [self::$VERSION_START_TAG, self::$VERSION_END_TAG, PHP_EOL],
array('', '', ''), ['', '', ''],
$data $data
); );
} }
@ -184,13 +185,15 @@ public static function checkResourcePermissions(ConfigManager $conf, bool $minim
$rainTplDir = rtrim($conf->get('resource.raintpl_tpl'), '/'); $rainTplDir = rtrim($conf->get('resource.raintpl_tpl'), '/');
// Check script and template directories are readable // Check script and template directories are readable
foreach ([ foreach (
[
'application', 'application',
'inc', 'inc',
'plugins', 'plugins',
$rainTplDir, $rainTplDir,
$rainTplDir . '/' . $conf->get('resource.theme'), $rainTplDir . '/' . $conf->get('resource.theme'),
] as $path) { ] as $path
) {
if (!is_readable(realpath($path))) { if (!is_readable(realpath($path))) {
$errors[] = '"' . $path . '" ' . t('directory is not readable'); $errors[] = '"' . $path . '" ' . t('directory is not readable');
} }
@ -224,13 +227,15 @@ public static function checkResourcePermissions(ConfigManager $conf, bool $minim
} }
// Check configuration files are readable and writable // Check configuration files are readable and writable
foreach (array( foreach (
[
$conf->getConfigFileExt(), $conf->getConfigFileExt(),
$conf->get('resource.datastore'), $conf->get('resource.datastore'),
$conf->get('resource.ban_file'), $conf->get('resource.ban_file'),
$conf->get('resource.log'), $conf->get('resource.log'),
$conf->get('resource.update_check'), $conf->get('resource.update_check'),
) as $path) { ] as $path
) {
if (!is_file(realpath($path))) { if (!is_file(realpath($path))) {
# the file may not exist yet # the file may not exist yet
continue; continue;

View file

@ -48,7 +48,7 @@ function get_http_response(
$cleanUrl = $urlObj->idnToAscii(); $cleanUrl = $urlObj->idnToAscii();
if (!filter_var($cleanUrl, FILTER_VALIDATE_URL) || !$urlObj->isHttp()) { if (!filter_var($cleanUrl, FILTER_VALIDATE_URL) || !$urlObj->isHttp()) {
return array(array(0 => 'Invalid HTTP UrlUtils'), false); return [[0 => 'Invalid HTTP UrlUtils'], false];
} }
$userAgent = $userAgent =
@ -71,7 +71,7 @@ function get_http_response(
$ch = curl_init($cleanUrl); $ch = curl_init($cleanUrl);
if ($ch === false) { if ($ch === false) {
return array(array(0 => 'curl_init() error'), false); return [[0 => 'curl_init() error'], false];
} }
// General cURL settings // General cURL settings
@ -82,7 +82,7 @@ function get_http_response(
curl_setopt( curl_setopt(
$ch, $ch,
CURLOPT_HTTPHEADER, CURLOPT_HTTPHEADER,
array('Accept-Language: ' . $acceptLanguage) ['Accept-Language: ' . $acceptLanguage]
); );
curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRedirs); curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRedirs);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@ -122,9 +122,9 @@ function ($arg0, $arg1, $arg2, $arg3, $arg4) use ($maxBytes) {
* Removing this would require updating * Removing this would require updating
* GetHttpUrlTest::testGetInvalidRemoteUrl() * GetHttpUrlTest::testGetInvalidRemoteUrl()
*/ */
return array(false, false); return [false, false];
} }
return array(array(0 => 'curl_exec() error: ' . $errorStr), false); return [[0 => 'curl_exec() error: ' . $errorStr], false];
} }
// Formatting output like the fallback method // Formatting output like the fallback method
@ -135,7 +135,7 @@ function ($arg0, $arg1, $arg2, $arg3, $arg4) use ($maxBytes) {
$rawHeadersLastRedir = end($rawHeadersArrayRedirs); $rawHeadersLastRedir = end($rawHeadersArrayRedirs);
$content = substr($response, $headSize); $content = substr($response, $headSize);
$headers = array(); $headers = [];
foreach (preg_split('~[\r\n]+~', $rawHeadersLastRedir) as $line) { foreach (preg_split('~[\r\n]+~', $rawHeadersLastRedir) as $line) {
if (empty($line) || ctype_space($line)) { if (empty($line) || ctype_space($line)) {
continue; continue;
@ -146,7 +146,7 @@ function ($arg0, $arg1, $arg2, $arg3, $arg4) use ($maxBytes) {
$value = $splitLine[1]; $value = $splitLine[1];
if (array_key_exists($key, $headers)) { if (array_key_exists($key, $headers)) {
if (!is_array($headers[$key])) { if (!is_array($headers[$key])) {
$headers[$key] = array(0 => $headers[$key]); $headers[$key] = [0 => $headers[$key]];
} }
$headers[$key][] = $value; $headers[$key][] = $value;
} else { } else {
@ -157,7 +157,7 @@ function ($arg0, $arg1, $arg2, $arg3, $arg4) use ($maxBytes) {
} }
} }
return array($headers, $content); return [$headers, $content];
} }
/** /**
@ -188,15 +188,15 @@ function get_http_response_fallback(
$acceptLanguage, $acceptLanguage,
$maxRedr $maxRedr
) { ) {
$options = array( $options = [
'http' => array( 'http' => [
'method' => 'GET', 'method' => 'GET',
'timeout' => $timeout, 'timeout' => $timeout,
'user_agent' => $userAgent, 'user_agent' => $userAgent,
'header' => "Accept: */*\r\n" 'header' => "Accept: */*\r\n"
. 'Accept-Language: ' . $acceptLanguage . 'Accept-Language: ' . $acceptLanguage
) ]
); ];
stream_context_set_default($options); stream_context_set_default($options);
list($headers, $finalUrl) = get_redirected_headers($cleanUrl, $maxRedr); list($headers, $finalUrl) = get_redirected_headers($cleanUrl, $maxRedr);
@ -207,7 +207,7 @@ function get_http_response_fallback(
} }
if (! $headers) { if (! $headers) {
return array($headers, false); return [$headers, false];
} }
try { try {
@ -215,10 +215,10 @@ function get_http_response_fallback(
$context = stream_context_create($options); $context = stream_context_create($options);
$content = file_get_contents($finalUrl, false, $context, -1, $maxBytes); $content = file_get_contents($finalUrl, false, $context, -1, $maxBytes);
} catch (Exception $exc) { } catch (Exception $exc) {
return array(array(0 => 'HTTP Error'), $exc->getMessage()); return [[0 => 'HTTP Error'], $exc->getMessage()];
} }
return array($headers, $content); return [$headers, $content];
} }
/** /**
@ -237,10 +237,12 @@ function get_redirected_headers($url, $redirectionLimit = 3)
} }
// Headers found, redirection found, and limit not reached. // Headers found, redirection found, and limit not reached.
if ($redirectionLimit-- > 0 if (
$redirectionLimit-- > 0
&& !empty($headers) && !empty($headers)
&& (strpos($headers[0], '301') !== false || strpos($headers[0], '302') !== false) && (strpos($headers[0], '301') !== false || strpos($headers[0], '302') !== false)
&& !empty($headers['Location'])) { && !empty($headers['Location'])
) {
$redirection = is_array($headers['Location']) ? end($headers['Location']) : $headers['Location']; $redirection = is_array($headers['Location']) ? end($headers['Location']) : $headers['Location'];
if ($redirection != $url) { if ($redirection != $url) {
$redirection = getAbsoluteUrl($url, $redirection); $redirection = getAbsoluteUrl($url, $redirection);
@ -248,7 +250,7 @@ function get_redirected_headers($url, $redirectionLimit = 3)
} }
} }
return array($headers, $url); return [$headers, $url];
} }
/** /**
@ -323,7 +325,8 @@ function server_url($server)
$scheme = 'https'; $scheme = 'https';
} }
if (($scheme == 'http' && $port != '80') if (
($scheme == 'http' && $port != '80')
|| ($scheme == 'https' && $port != '443') || ($scheme == 'https' && $port != '443')
) { ) {
$port = ':' . $port; $port = ':' . $port;
@ -348,14 +351,18 @@ function server_url($server)
} }
// SSL detection // SSL detection
if ((! empty($server['HTTPS']) && strtolower($server['HTTPS']) == 'on') if (
|| (isset($server['SERVER_PORT']) && $server['SERVER_PORT'] == '443')) { (! empty($server['HTTPS']) && strtolower($server['HTTPS']) == 'on')
|| (isset($server['SERVER_PORT']) && $server['SERVER_PORT'] == '443')
) {
$scheme = 'https'; $scheme = 'https';
} }
// Do not append standard port values // Do not append standard port values
if (($scheme == 'http' && $server['SERVER_PORT'] != '80') if (
|| ($scheme == 'https' && $server['SERVER_PORT'] != '443')) { ($scheme == 'http' && $server['SERVER_PORT'] != '80')
|| ($scheme == 'https' && $server['SERVER_PORT'] != '443')
) {
$port = ':' . $server['SERVER_PORT']; $port = ':' . $server['SERVER_PORT'];
} }
@ -567,7 +574,10 @@ function get_curl_download_callback(
* *
* @return int|bool length of $data or false if we need to stop the download * @return int|bool length of $data or false if we need to stop the download
*/ */
return function ($ch, $data) use ( return function (
$ch,
$data
) use (
$retrieveDescription, $retrieveDescription,
$tagsSeparator, $tagsSeparator,
&$charset, &$charset,
@ -611,7 +621,8 @@ function get_curl_download_callback(
// If we already found either the title, description or keywords, // If we already found either the title, description or keywords,
// it's highly unlikely that we'll found the other metas further than // it's highly unlikely that we'll found the other metas further than
// in the same chunk of data or the next one. So we also stop the download after that. // in the same chunk of data or the next one. So we also stop the download after that.
if ((!empty($responseCode) && !empty($contentType) && !empty($charset)) && $foundChunk !== null if (
(!empty($responseCode) && !empty($contentType) && !empty($charset)) && $foundChunk !== null
&& (! $retrieveDescription && (! $retrieveDescription
|| $foundChunk < $currentChunk || $foundChunk < $currentChunk
|| (!empty($title) && !empty($description) && !empty($keywords)) || (!empty($title) && !empty($description) && !empty($keywords))

View file

@ -17,7 +17,7 @@
*/ */
class Url class Url
{ {
private static $annoyingQueryParams = array( private static $annoyingQueryParams = [
// Facebook // Facebook
'action_object_map=', 'action_object_map=',
'action_ref_map=', 'action_ref_map=',
@ -37,15 +37,15 @@ class Url
// Other // Other
'campaign_' 'campaign_'
); ];
private static $annoyingFragments = array( private static $annoyingFragments = [
// ATInternet // ATInternet
'xtor=RSS-', 'xtor=RSS-',
// Misc. // Misc.
'tk.rss_all' 'tk.rss_all'
); ];
/* /*
* URL parts represented as an array * URL parts represented as an array
@ -120,7 +120,7 @@ protected function cleanupQuery()
foreach (self::$annoyingQueryParams as $annoying) { foreach (self::$annoyingQueryParams as $annoying) {
foreach ($queryParams as $param) { foreach ($queryParams as $param) {
if (startsWith($param, $annoying)) { if (startsWith($param, $annoying)) {
$queryParams = array_diff($queryParams, array($param)); $queryParams = array_diff($queryParams, [$param]);
continue; continue;
} }
} }

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Converts an array-represented URL to a string * Converts an array-represented URL to a string
* *

View file

@ -62,7 +62,7 @@ class LegacyLinkDB implements Iterator, Countable, ArrayAccess
private $datastore; private $datastore;
// Link date storage format // Link date storage format
const LINK_DATE_FORMAT = 'Ymd_His'; public const LINK_DATE_FORMAT = 'Ymd_His';
// List of bookmarks (associative array) // List of bookmarks (associative array)
// - key: link date (e.g. "20110823_124546"), // - key: link date (e.g. "20110823_124546"),
@ -240,8 +240,8 @@ private function check()
} }
// Create a dummy database for example // Create a dummy database for example
$this->links = array(); $this->links = [];
$link = array( $link = [
'id' => 1, 'id' => 1,
'title' => t('The personal, minimalist, super-fast, database free, bookmarking service'), 'title' => t('The personal, minimalist, super-fast, database free, bookmarking service'),
'url' => 'https://shaarli.readthedocs.io', 'url' => 'https://shaarli.readthedocs.io',
@ -257,11 +257,11 @@ private function check()
'created' => new DateTime(), 'created' => new DateTime(),
'tags' => 'opensource software', 'tags' => 'opensource software',
'sticky' => false, 'sticky' => false,
); ];
$link['shorturl'] = link_small_hash($link['created'], $link['id']); $link['shorturl'] = link_small_hash($link['created'], $link['id']);
$this->links[1] = $link; $this->links[1] = $link;
$link = array( $link = [
'id' => 0, 'id' => 0,
'title' => t('My secret stuff... - Pastebin.com'), 'title' => t('My secret stuff... - Pastebin.com'),
'url' => 'http://sebsauvage.net/paste/?8434b27936c09649#bR7XsXhoTiLcqCpQbmOpBi3rq2zzQUC5hBI7ZT1O3x8=', 'url' => 'http://sebsauvage.net/paste/?8434b27936c09649#bR7XsXhoTiLcqCpQbmOpBi3rq2zzQUC5hBI7ZT1O3x8=',
@ -270,7 +270,7 @@ private function check()
'created' => new DateTime('1 minute ago'), 'created' => new DateTime('1 minute ago'),
'tags' => 'secretstuff', 'tags' => 'secretstuff',
'sticky' => false, 'sticky' => false,
); ];
$link['shorturl'] = link_small_hash($link['created'], $link['id']); $link['shorturl'] = link_small_hash($link['created'], $link['id']);
$this->links[0] = $link; $this->links[0] = $link;
@ -285,7 +285,7 @@ private function read()
{ {
// Public bookmarks are hidden and user not logged in => nothing to show // Public bookmarks are hidden and user not logged in => nothing to show
if ($this->hidePublicLinks && !$this->loggedIn) { if ($this->hidePublicLinks && !$this->loggedIn) {
$this->links = array(); $this->links = [];
return; return;
} }
@ -293,7 +293,7 @@ private function read()
$this->ids = []; $this->ids = [];
$this->links = FileUtils::readFlatDB($this->datastore, []); $this->links = FileUtils::readFlatDB($this->datastore, []);
$toremove = array(); $toremove = [];
foreach ($this->links as $key => &$link) { foreach ($this->links as $key => &$link) {
if (!$this->loggedIn && $link['private'] != 0) { if (!$this->loggedIn && $link['private'] != 0) {
// Transition for not upgraded databases. // Transition for not upgraded databases.
@ -414,7 +414,7 @@ public function filterDay($request)
* @return array filtered bookmarks, all bookmarks if no suitable filter was provided. * @return array filtered bookmarks, all bookmarks if no suitable filter was provided.
*/ */
public function filterSearch( public function filterSearch(
$filterRequest = array(), $filterRequest = [],
$casesensitive = false, $casesensitive = false,
$visibility = 'all', $visibility = 'all',
$untaggedonly = false $untaggedonly = false
@ -512,7 +512,7 @@ public function renameTag($from, $to)
*/ */
public function days() public function days()
{ {
$linkDays = array(); $linkDays = [];
foreach ($this->links as $link) { foreach ($this->links as $link) {
$linkDays[$link['created']->format('Ymd')] = 0; $linkDays[$link['created']->format('Ymd')] = 0;
} }

View file

@ -120,7 +120,7 @@ private function noFilter($visibility = 'all')
return $this->links; return $this->links;
} }
$out = array(); $out = [];
foreach ($this->links as $key => $value) { foreach ($this->links as $key => $value) {
if ($value['private'] && $visibility === 'private') { if ($value['private'] && $visibility === 'private') {
$out[$key] = $value; $out[$key] = $value;
@ -143,7 +143,7 @@ private function noFilter($visibility = 'all')
*/ */
private function filterSmallHash($smallHash) private function filterSmallHash($smallHash)
{ {
$filtered = array(); $filtered = [];
foreach ($this->links as $key => $l) { foreach ($this->links as $key => $l) {
if ($smallHash == $l['shorturl']) { if ($smallHash == $l['shorturl']) {
// Yes, this is ugly and slow // Yes, this is ugly and slow
@ -186,7 +186,7 @@ private function filterFulltext($searchterms, $visibility = 'all')
return $this->noFilter($visibility); return $this->noFilter($visibility);
} }
$filtered = array(); $filtered = [];
$search = mb_convert_case(html_entity_decode($searchterms), MB_CASE_LOWER, 'UTF-8'); $search = mb_convert_case(html_entity_decode($searchterms), MB_CASE_LOWER, 'UTF-8');
$exactRegex = '/"([^"]+)"/'; $exactRegex = '/"([^"]+)"/';
// Retrieve exact search terms. // Retrieve exact search terms.
@ -198,8 +198,8 @@ private function filterFulltext($searchterms, $visibility = 'all')
$explodedSearchAnd = array_values(array_filter($explodedSearchAnd)); $explodedSearchAnd = array_values(array_filter($explodedSearchAnd));
// Filter excluding terms and update andSearch. // Filter excluding terms and update andSearch.
$excludeSearch = array(); $excludeSearch = [];
$andSearch = array(); $andSearch = [];
foreach ($explodedSearchAnd as $needle) { foreach ($explodedSearchAnd as $needle) {
if ($needle[0] == '-' && strlen($needle) > 1) { if ($needle[0] == '-' && strlen($needle) > 1) {
$excludeSearch[] = substr($needle, 1); $excludeSearch[] = substr($needle, 1);
@ -208,7 +208,7 @@ private function filterFulltext($searchterms, $visibility = 'all')
} }
} }
$keys = array('title', 'description', 'url', 'tags'); $keys = ['title', 'description', 'url', 'tags'];
// Iterate over every stored link. // Iterate over every stored link.
foreach ($this->links as $id => $link) { foreach ($this->links as $id => $link) {
@ -336,7 +336,7 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
} }
// create resulting array // create resulting array
$filtered = array(); $filtered = [];
// iterate over each link // iterate over each link
foreach ($this->links as $key => $link) { foreach ($this->links as $key => $link) {
@ -352,7 +352,7 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
$search = $link['tags']; // build search string, start with tags of current link $search = $link['tags']; // build search string, start with tags of current link
if (strlen(trim($link['description'])) && strpos($link['description'], '#') !== false) { if (strlen(trim($link['description'])) && strpos($link['description'], '#') !== false) {
// description given and at least one possible tag found // description given and at least one possible tag found
$descTags = array(); $descTags = [];
// find all tags in the form of #tag in the description // find all tags in the form of #tag in the description
preg_match_all( preg_match_all(
'/(?<![' . self::$HASHTAG_CHARS . '])#([' . self::$HASHTAG_CHARS . ']+?)\b/sm', '/(?<![' . self::$HASHTAG_CHARS . '])#([' . self::$HASHTAG_CHARS . ']+?)\b/sm',
@ -419,7 +419,7 @@ public function filterDay($day)
throw new Exception('Invalid date format'); throw new Exception('Invalid date format');
} }
$filtered = array(); $filtered = [];
foreach ($this->links as $key => $l) { foreach ($this->links as $key => $l) {
if ($l['created']->format('Ymd') == $day) { if ($l['created']->format('Ymd') == $day) {
$filtered[$key] = $l; $filtered[$key] = $l;

View file

@ -93,7 +93,7 @@ public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn, &$session
*/ */
public function update() public function update()
{ {
$updatesRan = array(); $updatesRan = [];
// If the user isn't logged in, exit without updating. // If the user isn't logged in, exit without updating.
if ($this->isLoggedIn !== true) { if ($this->isLoggedIn !== true) {
@ -106,7 +106,8 @@ public function update()
foreach ($this->methods as $method) { foreach ($this->methods as $method) {
// Not an update method or already done, pass. // Not an update method or already done, pass.
if (!startsWith($method->getName(), 'updateMethod') if (
!startsWith($method->getName(), 'updateMethod')
|| in_array($method->getName(), $this->doneUpdates) || in_array($method->getName(), $this->doneUpdates)
) { ) {
continue; continue;
@ -189,7 +190,7 @@ public function updateMethodConfigToJson()
} }
// Set sub config keys (config and plugins) // Set sub config keys (config and plugins)
$subConfig = array('config', 'plugins'); $subConfig = ['config', 'plugins'];
foreach ($subConfig as $sub) { foreach ($subConfig as $sub) {
foreach ($oldConfig[$sub] as $key => $value) { foreach ($oldConfig[$sub] as $key => $value) {
if (isset($legacyMap[$sub . '.' . $key])) { if (isset($legacyMap[$sub . '.' . $key])) {
@ -259,7 +260,7 @@ public function updateMethodDatastoreIds()
$save = $this->conf->get('resource.data_dir') . '/datastore.' . date('YmdHis') . '.php'; $save = $this->conf->get('resource.data_dir') . '/datastore.' . date('YmdHis') . '.php';
copy($this->conf->get('resource.datastore'), $save); copy($this->conf->get('resource.datastore'), $save);
$links = array(); $links = [];
foreach ($this->linkDB as $offset => $value) { foreach ($this->linkDB as $offset => $value) {
$links[] = $value; $links[] = $value;
unset($this->linkDB[$offset]); unset($this->linkDB[$offset]);
@ -498,7 +499,8 @@ public function updateMethodVisibilitySession()
*/ */
public function updateMethodDownloadSizeAndTimeoutConf() public function updateMethodDownloadSizeAndTimeoutConf()
{ {
if ($this->conf->exists('general.download_max_size') if (
$this->conf->exists('general.download_max_size')
&& $this->conf->exists('general.download_timeout') && $this->conf->exists('general.download_timeout')
) { ) {
return true; return true;

View file

@ -59,11 +59,11 @@ public function filterAndFormat(
$indexUrl $indexUrl
) { ) {
// see tpl/export.html for possible values // see tpl/export.html for possible values
if (!in_array($selection, array('all', 'public', 'private'))) { if (!in_array($selection, ['all', 'public', 'private'])) {
throw new Exception(t('Invalid export selection:') . ' "' . $selection . '"'); throw new Exception(t('Invalid export selection:') . ' "' . $selection . '"');
} }
$bookmarkLinks = array(); $bookmarkLinks = [];
foreach ($this->bookmarkService->search([], $selection) as $bookmark) { foreach ($this->bookmarkService->search([], $selection) as $bookmark) {
$link = $formatter->format($bookmark); $link = $formatter->format($bookmark);
$link['taglist'] = implode(',', $bookmark->getTags()); $link['taglist'] = implode(',', $bookmark->getTags());

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Plugin; namespace Shaarli\Plugin;
use Shaarli\Config\ConfigManager; use Shaarli\Config\ConfigManager;
@ -23,7 +24,7 @@ class PluginManager
* *
* @var array $loadedPlugins * @var array $loadedPlugins
*/ */
private $loadedPlugins = array(); private $loadedPlugins = [];
/** /**
* @var ConfigManager Configuration Manager instance. * @var ConfigManager Configuration Manager instance.
@ -57,7 +58,7 @@ class PluginManager
public function __construct(&$conf) public function __construct(&$conf)
{ {
$this->conf = $conf; $this->conf = $conf;
$this->errors = array(); $this->errors = [];
} }
/** /**
@ -98,7 +99,7 @@ public function load($authorizedPlugins)
* *
* @return void * @return void
*/ */
public function executeHooks($hook, &$data, $params = array()) public function executeHooks($hook, &$data, $params = [])
{ {
$metadataParameters = [ $metadataParameters = [
'target' => '_PAGE_', 'target' => '_PAGE_',
@ -196,7 +197,7 @@ public function buildHookName($hook, $pluginName)
*/ */
public function getPluginsMeta() public function getPluginsMeta()
{ {
$metaData = array(); $metaData = [];
$dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR | GLOB_MARK); $dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR | GLOB_MARK);
// Browse all plugin directories. // Browse all plugin directories.
@ -217,9 +218,9 @@ public function getPluginsMeta()
if (isset($metaData[$plugin]['parameters'])) { if (isset($metaData[$plugin]['parameters'])) {
$params = explode(';', $metaData[$plugin]['parameters']); $params = explode(';', $metaData[$plugin]['parameters']);
} else { } else {
$params = array(); $params = [];
} }
$metaData[$plugin]['parameters'] = array(); $metaData[$plugin]['parameters'] = [];
foreach ($params as $param) { foreach ($params as $param) {
if (empty($param)) { if (empty($param)) {
continue; continue;

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Plugin\Exception; namespace Shaarli\Plugin\Exception;
use Exception; use Exception;

View file

@ -1,6 +1,5 @@
<?php <?php
namespace Shaarli\Security; namespace Shaarli\Security;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -47,7 +46,8 @@ class BanManager
* @param string $banFile Path to the file containing IP bans and failures * @param string $banFile Path to the file containing IP bans and failures
* @param LoggerInterface $logger PSR-3 logger to save login attempts in log directory * @param LoggerInterface $logger PSR-3 logger to save login attempts in log directory
*/ */
public function __construct($trustedProxies, $nbAttempts, $banDuration, $banFile, LoggerInterface $logger) { public function __construct($trustedProxies, $nbAttempts, $banDuration, $banFile, LoggerInterface $logger)
{
$this->trustedProxies = $trustedProxies; $this->trustedProxies = $trustedProxies;
$this->nbAttempts = $nbAttempts; $this->nbAttempts = $nbAttempts;
$this->banDuration = $banDuration; $this->banDuration = $banDuration;

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Security; namespace Shaarli\Security;
use Exception; use Exception;
@ -106,7 +107,8 @@ public function checkLoginState($clientIpId)
// The user client has a valid stay-signed-in cookie // The user client has a valid stay-signed-in cookie
// Session information is updated with the current client information // Session information is updated with the current client information
$this->sessionManager->storeLoginInfo($clientIpId); $this->sessionManager->storeLoginInfo($clientIpId);
} elseif ($this->sessionManager->hasSessionExpired() } elseif (
$this->sessionManager->hasSessionExpired()
|| $this->sessionManager->hasClientIpChanged($clientIpId) || $this->sessionManager->hasClientIpChanged($clientIpId)
) { ) {
$this->sessionManager->logout(); $this->sessionManager->logout();
@ -145,7 +147,8 @@ public function checkCredentials($clientIpId, $login, $password)
// Check credentials // Check credentials
try { try {
$useLdapLogin = !empty($this->configManager->get('ldap.host')); $useLdapLogin = !empty($this->configManager->get('ldap.host'));
if ($login === $this->configManager->get('credentials.login') if (
$login === $this->configManager->get('credentials.login')
&& ( && (
(false === $useLdapLogin && $this->checkCredentialsFromLocalConfig($login, $password)) (false === $useLdapLogin && $this->checkCredentialsFromLocalConfig($login, $password))
|| (true === $useLdapLogin && $this->checkCredentialsFromLdap($login, $password)) || (true === $useLdapLogin && $this->checkCredentialsFromLdap($login, $password))
@ -174,7 +177,8 @@ public function checkCredentials($clientIpId, $login, $password)
* *
* @return bool true if the provided credentials are valid, false otherwise * @return bool true if the provided credentials are valid, false otherwise
*/ */
public function checkCredentialsFromLocalConfig($login, $password) { public function checkCredentialsFromLocalConfig($login, $password)
{
$hash = sha1($password . $login . $this->configManager->get('credentials.salt')); $hash = sha1($password . $login . $this->configManager->get('credentials.salt'));
return $login == $this->configManager->get('credentials.login') return $login == $this->configManager->get('credentials.login')

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Security; namespace Shaarli\Security;
use Shaarli\Config\ConfigManager; use Shaarli\Config\ConfigManager;

View file

@ -88,7 +88,8 @@ public function update(string $basePath = null)
foreach ($this->methods as $method) { foreach ($this->methods as $method) {
// Not an update method or already done, pass. // Not an update method or already done, pass.
if (! startsWith($method->getName(), 'updateMethod') if (
! startsWith($method->getName(), 'updateMethod')
|| in_array($method->getName(), $this->doneUpdates) || in_array($method->getName(), $this->doneUpdates)
) { ) {
continue; continue;
@ -121,12 +122,12 @@ public function getDoneUpdates()
public function readUpdates(string $updatesFilepath): array public function readUpdates(string $updatesFilepath): array
{ {
return UpdaterUtils::read_updates_file($updatesFilepath); return UpdaterUtils::readUpdatesFile($updatesFilepath);
} }
public function writeUpdates(string $updatesFilepath, array $updates): void public function writeUpdates(string $updatesFilepath, array $updates): void
{ {
UpdaterUtils::write_updates_file($updatesFilepath, $updates); UpdaterUtils::writeUpdatesFile($updatesFilepath, $updates);
} }
/** /**
@ -152,7 +153,8 @@ public function updateMethodMigrateExistingNotesUrl(): bool
$updated = false; $updated = false;
foreach ($this->bookmarkService->search() as $bookmark) { foreach ($this->bookmarkService->search() as $bookmark) {
if ($bookmark->isNote() if (
$bookmark->isNote()
&& startsWith($bookmark->getUrl(), '?') && startsWith($bookmark->getUrl(), '?')
&& 1 === preg_match('/^\?([a-zA-Z0-9-_@]{6})($|&|#)/', $bookmark->getUrl(), $match) && 1 === preg_match('/^\?([a-zA-Z0-9-_@]{6})($|&|#)/', $bookmark->getUrl(), $match)
) { ) {

View file

@ -11,7 +11,7 @@ class UpdaterUtils
* *
* @return array Already done update methods. * @return array Already done update methods.
*/ */
public static function read_updates_file($updatesFilepath) public static function readUpdatesFile($updatesFilepath)
{ {
if (! empty($updatesFilepath) && is_file($updatesFilepath)) { if (! empty($updatesFilepath) && is_file($updatesFilepath)) {
$content = file_get_contents($updatesFilepath); $content = file_get_contents($updatesFilepath);
@ -19,7 +19,7 @@ public static function read_updates_file($updatesFilepath)
return explode(';', $content); return explode(';', $content);
} }
} }
return array(); return [];
} }
/** /**
@ -30,7 +30,7 @@ public static function read_updates_file($updatesFilepath)
* *
* @throws \Exception Couldn't write version number. * @throws \Exception Couldn't write version number.
*/ */
public static function write_updates_file($updatesFilepath, $updates) public static function writeUpdatesFile($updatesFilepath, $updates)
{ {
if (empty($updatesFilepath)) { if (empty($updatesFilepath)) {
throw new \Exception('Updates file path is not set, can\'t write updates.'); throw new \Exception('Updates file path is not set, can\'t write updates.');

View file

@ -163,11 +163,13 @@ See [`.travis.yml`](https://github.com/shaarli/Shaarli/blob/master/.travis.yml).
## Static analysis ## Static analysis
Patches should try to stick to the [PHP Standard Recommendations](http://www.php-fig.org/psr/) (PSR), especially: Patches should try to stick to the [PHP Standard Recommendations](http://www.php-fig.org/psr/) (PSR), and must follow:
- [PSR-1](http://www.php-fig.org/psr/psr-1/) - Basic Coding Standard - [PSR-1](http://www.php-fig.org/psr/psr-1/) - Basic Coding Standard
- [PSR-2](http://www.php-fig.org/psr/psr-2/) - Coding Style Guide - [PSR-2](http://www.php-fig.org/psr/psr-2/) - Coding Style Guide
- [PSR-12](http://www.php-fig.org/psr/psr-12/) - Extended Coding Style Guide
These are enforced on pull requests using our Continuous Integration tools.
**Work in progress:** Static analysis is currently being discussed here: in [#95 - Fix coding style (static analysis)](https://github.com/shaarli/Shaarli/issues/95), [#130 - Continuous Integration tools & features](https://github.com/shaarli/Shaarli/issues/130) **Work in progress:** Static analysis is currently being discussed here: in [#95 - Fix coding style (static analysis)](https://github.com/shaarli/Shaarli/issues/95), [#130 - Continuous Integration tools & features](https://github.com/shaarli/Shaarli/issues/130)

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Shaarli - The personal, minimalist, super-fast, database free, bookmarking service. * Shaarli - The personal, minimalist, super-fast, database free, bookmarking service.
* *

View file

@ -5,13 +5,18 @@
<file>index.php</file> <file>index.php</file>
<file>application</file> <file>application</file>
<file>plugins</file> <file>plugins</file>
<file>tests</file> <!-- <file>tests</file>-->
<exclude-pattern>*/*.css</exclude-pattern> <exclude-pattern>*/*.css</exclude-pattern>
<exclude-pattern>*/*.js</exclude-pattern> <exclude-pattern>*/*.js</exclude-pattern>
<arg name="colors"/> <arg name="colors"/>
<rule ref="PSR1"/> <rule ref="PSR12"/>
<rule ref="PSR2"/> <rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
<rule ref="PSR1.Files.SideEffects.FoundWithSymbols">
<!-- index.php bootstraps everything, so yes mixed symbols with side effects -->
<exclude-pattern>index.php</exclude-pattern>
</rule>
</ruleset> </ruleset>

View file

@ -17,26 +17,26 @@
function hook_addlink_toolbar_render_header($data) function hook_addlink_toolbar_render_header($data)
{ {
if ($data['_PAGE_'] == TemplatePage::LINKLIST && $data['_LOGGEDIN_'] === true) { if ($data['_PAGE_'] == TemplatePage::LINKLIST && $data['_LOGGEDIN_'] === true) {
$form = array( $form = [
'attr' => array( 'attr' => [
'method' => 'GET', 'method' => 'GET',
'action' => $data['_BASE_PATH_'] . '/admin/shaare', 'action' => $data['_BASE_PATH_'] . '/admin/shaare',
'name' => 'addform', 'name' => 'addform',
'class' => 'addform', 'class' => 'addform',
), ],
'inputs' => array( 'inputs' => [
array( [
'type' => 'text', 'type' => 'text',
'name' => 'post', 'name' => 'post',
'placeholder' => t('URI'), 'placeholder' => t('URI'),
), ],
array( [
'type' => 'submit', 'type' => 'submit',
'value' => t('Add link'), 'value' => t('Add link'),
'class' => 'bigbutton', 'class' => 'bigbutton',
), ],
), ],
); ];
$data['fields_toolbar'][] = $form; $data['fields_toolbar'][] = $form;
} }

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Plugin Archive.org. * Plugin Archive.org.
* *

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Demo Plugin. * Demo Plugin.
* *
@ -82,14 +83,14 @@ function hook_demo_plugin_render_header($data)
* A link is an array of its attributes (key="value"), * A link is an array of its attributes (key="value"),
* and a mandatory `html` key, which contains its value. * and a mandatory `html` key, which contains its value.
*/ */
$button = array( $button = [
'attr' => array ( 'attr' => [
'href' => '#', 'href' => '#',
'class' => 'mybutton', 'class' => 'mybutton',
'title' => 'hover me', 'title' => 'hover me',
), ],
'html' => 'DEMO buttons toolbar', 'html' => 'DEMO buttons toolbar',
); ];
$data['buttons_toolbar'][] = $button; $data['buttons_toolbar'][] = $button;
} }
@ -115,29 +116,29 @@ function hook_demo_plugin_render_header($data)
* <input input-2-attribute-1="input 2 attribute 1 value"> * <input input-2-attribute-1="input 2 attribute 1 value">
* </form> * </form>
*/ */
$form = array( $form = [
'attr' => array( 'attr' => [
'method' => 'GET', 'method' => 'GET',
'action' => $data['_BASE_PATH_'] . '/', 'action' => $data['_BASE_PATH_'] . '/',
'class' => 'addform', 'class' => 'addform',
), ],
'inputs' => array( 'inputs' => [
array( [
'type' => 'text', 'type' => 'text',
'name' => 'demo', 'name' => 'demo',
'placeholder' => 'demo', 'placeholder' => 'demo',
) ]
) ]
); ];
$data['fields_toolbar'][] = $form; $data['fields_toolbar'][] = $form;
} }
// Another button always displayed // Another button always displayed
$button = array( $button = [
'attr' => array( 'attr' => [
'href' => '#', 'href' => '#',
), ],
'html' => 'Demo', 'html' => 'Demo',
); ];
$data['buttons_toolbar'][] = $button; $data['buttons_toolbar'][] = $button;
return $data; return $data;
@ -229,13 +230,13 @@ function hook_demo_plugin_render_linklist($data)
* and a mandatory `html` key, which contains its value. * and a mandatory `html` key, which contains its value.
* It's also recommended to add key 'on' or 'off' for theme rendering. * It's also recommended to add key 'on' or 'off' for theme rendering.
*/ */
$action = array( $action = [
'attr' => array( 'attr' => [
'href' => '?up', 'href' => '?up',
'title' => 'Uppercase!', 'title' => 'Uppercase!',
), ],
'html' => '←', 'html' => '←',
); ];
if (isset($_GET['up'])) { if (isset($_GET['up'])) {
// Manipulate link data // Manipulate link data

View file

@ -21,7 +21,7 @@ function isso_init($conf)
if (empty($issoUrl)) { if (empty($issoUrl)) {
$error = t('Isso plugin error: ' . $error = t('Isso plugin error: ' .
'Please define the "ISSO_SERVER" setting in the plugin administration page.'); 'Please define the "ISSO_SERVER" setting in the plugin administration page.');
return array($error); return [$error];
} }
} }

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Piwik plugin. * Piwik plugin.
* Adds tracking code on each page. * Adds tracking code on each page.
@ -22,7 +23,7 @@ function piwik_init($conf)
if (empty($piwikUrl) || empty($piwikSiteid)) { if (empty($piwikUrl) || empty($piwikSiteid)) {
$error = t('Piwik plugin error: ' . $error = t('Piwik plugin error: ' .
'Please define PIWIK_URL and PIWIK_SITEID in the plugin administration page.'); 'Please define PIWIK_URL and PIWIK_SITEID in the plugin administration page.');
return array($error); return [$error];
} }
} }

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Plugin PlayVideos * Plugin PlayVideos
* *
@ -19,14 +20,14 @@
function hook_playvideos_render_header($data) function hook_playvideos_render_header($data)
{ {
if ($data['_PAGE_'] == TemplatePage::LINKLIST) { if ($data['_PAGE_'] == TemplatePage::LINKLIST) {
$playvideo = array( $playvideo = [
'attr' => array( 'attr' => [
'href' => '#', 'href' => '#',
'title' => t('Video player'), 'title' => t('Video player'),
'id' => 'playvideos', 'id' => 'playvideos',
), ],
'html' => '► ' . t('Play Videos') 'html' => '► ' . t('Play Videos')
); ];
$data['buttons_toolbar'][] = $playvideo; $data['buttons_toolbar'][] = $playvideo;
} }

View file

@ -59,10 +59,10 @@ function hook_pubsubhubbub_render_feed($data, $conf)
*/ */
function hook_pubsubhubbub_save_link($data, $conf) function hook_pubsubhubbub_save_link($data, $conf)
{ {
$feeds = array( $feeds = [
index_url($_SERVER) . 'feed/atom', index_url($_SERVER) . 'feed/atom',
index_url($_SERVER) . 'feed/rss', index_url($_SERVER) . 'feed/rss',
); ];
$httpPost = function_exists('curl_version') ? false : 'nocurl_http_post'; $httpPost = function_exists('curl_version') ? false : 'nocurl_http_post';
try { try {
@ -87,11 +87,11 @@ function hook_pubsubhubbub_save_link($data, $conf)
*/ */
function nocurl_http_post($url, $postString) function nocurl_http_post($url, $postString)
{ {
$params = array('http' => array( $params = ['http' => [
'method' => 'POST', 'method' => 'POST',
'content' => $postString, 'content' => $postString,
'user_agent' => 'PubSubHubbub-Publisher-PHP/1.0', 'user_agent' => 'PubSubHubbub-Publisher-PHP/1.0',
)); ]];
$context = stream_context_create($params); $context = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $context); $fp = @fopen($url, 'rb', false, $context);

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Plugin qrcode * Plugin qrcode
* Add QRCode containing URL for each links. * Add QRCode containing URL for each links.

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Shaarli\Plugin\Wallabag; namespace Shaarli\Plugin\Wallabag;
/** /**
@ -11,20 +12,20 @@ class WallabagInstance
* - key: version ID, must match plugin settings. * - key: version ID, must match plugin settings.
* - value: version name. * - value: version name.
*/ */
private static $wallabagVersions = array( private static $wallabagVersions = [
1 => '1.x', 1 => '1.x',
2 => '2.x', 2 => '2.x',
); ];
/** /**
* @var array Static reference to WB endpoint according to the API version. * @var array Static reference to WB endpoint according to the API version.
* - key: version name. * - key: version name.
* - value: endpoint. * - value: endpoint.
*/ */
private static $wallabagEndpoints = array( private static $wallabagEndpoints = [
'1.x' => '?plainurl=', '1.x' => '?plainurl=',
'2.x' => 'bookmarklet?url=', '2.x' => 'bookmarklet?url=',
); ];
/** /**
* @var string Wallabag user instance URL. * @var string Wallabag user instance URL.

View file

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Wallabag plugin * Wallabag plugin
*/ */
@ -20,7 +21,7 @@ function wallabag_init($conf)
if (empty($wallabagUrl)) { if (empty($wallabagUrl)) {
$error = t('Wallabag plugin error: ' . $error = t('Wallabag plugin error: ' .
'Please define the "WALLABAG_URL" setting in the plugin administration page.'); 'Please define the "WALLABAG_URL" setting in the plugin administration page.');
return array($error); return [$error];
} }
$conf->setEmpty('plugins.WALLABAG_URL', '2'); $conf->setEmpty('plugins.WALLABAG_URL', '2');
} }

View file

@ -51,10 +51,10 @@ protected function setUp(): void
*/ */
public function testReadEmptyUpdatesFile() public function testReadEmptyUpdatesFile()
{ {
$this->assertEquals(array(), UpdaterUtils::read_updates_file('')); $this->assertEquals(array(), UpdaterUtils::readUpdatesFile(''));
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt'; $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
touch($updatesFile); touch($updatesFile);
$this->assertEquals(array(), UpdaterUtils::read_updates_file($updatesFile)); $this->assertEquals(array(), UpdaterUtils::readUpdatesFile($updatesFile));
unlink($updatesFile); unlink($updatesFile);
} }
@ -66,14 +66,14 @@ public function testReadWriteUpdatesFile()
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt'; $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
$updatesMethods = array('m1', 'm2', 'm3'); $updatesMethods = array('m1', 'm2', 'm3');
UpdaterUtils::write_updates_file($updatesFile, $updatesMethods); UpdaterUtils::writeUpdatesFile($updatesFile, $updatesMethods);
$readMethods = UpdaterUtils::read_updates_file($updatesFile); $readMethods = UpdaterUtils::readUpdatesFile($updatesFile);
$this->assertEquals($readMethods, $updatesMethods); $this->assertEquals($readMethods, $updatesMethods);
// Update // Update
$updatesMethods[] = 'm4'; $updatesMethods[] = 'm4';
UpdaterUtils::write_updates_file($updatesFile, $updatesMethods); UpdaterUtils::writeUpdatesFile($updatesFile, $updatesMethods);
$readMethods = UpdaterUtils::read_updates_file($updatesFile); $readMethods = UpdaterUtils::readUpdatesFile($updatesFile);
$this->assertEquals($readMethods, $updatesMethods); $this->assertEquals($readMethods, $updatesMethods);
unlink($updatesFile); unlink($updatesFile);
} }
@ -86,7 +86,7 @@ public function testWriteEmptyUpdatesFile()
$this->expectException(\Exception::class); $this->expectException(\Exception::class);
$this->expectExceptionMessageRegExp('/Updates file path is not set(.*)/'); $this->expectExceptionMessageRegExp('/Updates file path is not set(.*)/');
UpdaterUtils::write_updates_file('', array('test')); UpdaterUtils::writeUpdatesFile('', array('test'));
} }
/** /**
@ -101,7 +101,7 @@ public function testWriteUpdatesFileNotWritable()
touch($updatesFile); touch($updatesFile);
chmod($updatesFile, 0444); chmod($updatesFile, 0444);
try { try {
@UpdaterUtils::write_updates_file($updatesFile, array('test')); @UpdaterUtils::writeUpdatesFile($updatesFile, array('test'));
} catch (Exception $e) { } catch (Exception $e) {
unlink($updatesFile); unlink($updatesFile);
throw $e; throw $e;

View file

@ -60,10 +60,10 @@ protected function setUp(): void
*/ */
public function testReadEmptyUpdatesFile() public function testReadEmptyUpdatesFile()
{ {
$this->assertEquals(array(), UpdaterUtils::read_updates_file('')); $this->assertEquals(array(), UpdaterUtils::readUpdatesFile(''));
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt'; $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
touch($updatesFile); touch($updatesFile);
$this->assertEquals(array(), UpdaterUtils::read_updates_file($updatesFile)); $this->assertEquals(array(), UpdaterUtils::readUpdatesFile($updatesFile));
unlink($updatesFile); unlink($updatesFile);
} }
@ -75,14 +75,14 @@ public function testReadWriteUpdatesFile()
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt'; $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
$updatesMethods = array('m1', 'm2', 'm3'); $updatesMethods = array('m1', 'm2', 'm3');
UpdaterUtils::write_updates_file($updatesFile, $updatesMethods); UpdaterUtils::writeUpdatesFile($updatesFile, $updatesMethods);
$readMethods = UpdaterUtils::read_updates_file($updatesFile); $readMethods = UpdaterUtils::readUpdatesFile($updatesFile);
$this->assertEquals($readMethods, $updatesMethods); $this->assertEquals($readMethods, $updatesMethods);
// Update // Update
$updatesMethods[] = 'm4'; $updatesMethods[] = 'm4';
UpdaterUtils::write_updates_file($updatesFile, $updatesMethods); UpdaterUtils::writeUpdatesFile($updatesFile, $updatesMethods);
$readMethods = UpdaterUtils::read_updates_file($updatesFile); $readMethods = UpdaterUtils::readUpdatesFile($updatesFile);
$this->assertEquals($readMethods, $updatesMethods); $this->assertEquals($readMethods, $updatesMethods);
unlink($updatesFile); unlink($updatesFile);
} }
@ -95,7 +95,7 @@ public function testWriteEmptyUpdatesFile()
$this->expectException(\Exception::class); $this->expectException(\Exception::class);
$this->expectExceptionMessageRegExp('/Updates file path is not set(.*)/'); $this->expectExceptionMessageRegExp('/Updates file path is not set(.*)/');
UpdaterUtils::write_updates_file('', array('test')); UpdaterUtils::writeUpdatesFile('', array('test'));
} }
/** /**
@ -110,7 +110,7 @@ public function testWriteUpdatesFileNotWritable()
touch($updatesFile); touch($updatesFile);
chmod($updatesFile, 0444); chmod($updatesFile, 0444);
try { try {
@UpdaterUtils::write_updates_file($updatesFile, array('test')); @UpdaterUtils::writeUpdatesFile($updatesFile, array('test'));
} catch (Exception $e) { } catch (Exception $e) {
unlink($updatesFile); unlink($updatesFile);
throw $e; throw $e;