Merge pull request #1234 from virtualtam/lint
Setup PHPCS and cleanup linter configuration
This commit is contained in:
commit
1004742f09
63 changed files with 432 additions and 724 deletions
68
Makefile
68
Makefile
|
@ -2,8 +2,6 @@
|
|||
# Makefile for PHP code analysis & testing, documentation and release generation
|
||||
|
||||
BIN = vendor/bin
|
||||
PHP_SOURCE = index.php application tests plugins
|
||||
PHP_COMMA_SOURCE = index.php,application,tests,plugins
|
||||
|
||||
all: static_analysis_summary check_permissions test
|
||||
|
||||
|
@ -17,14 +15,6 @@ docker_%:
|
|||
rsync -az /shaarli/ ~/shaarli/
|
||||
cd ~/shaarli && make $*
|
||||
|
||||
##
|
||||
# Concise status of the project
|
||||
# These targets are non-blocking: || exit 0
|
||||
##
|
||||
|
||||
static_analysis_summary: code_sniffer_source copy_paste mess_detector_summary
|
||||
@echo
|
||||
|
||||
##
|
||||
# PHP_CodeSniffer
|
||||
# Detects PHP syntax errors
|
||||
|
@ -32,70 +22,26 @@ static_analysis_summary: code_sniffer_source copy_paste mess_detector_summary
|
|||
# - http://pear.php.net/manual/en/package.php.php-codesniffer.usage.php
|
||||
# - http://pear.php.net/manual/en/package.php.php-codesniffer.reporting.php
|
||||
##
|
||||
PHPCS := $(BIN)/phpcs
|
||||
|
||||
code_sniffer: code_sniffer_full
|
||||
code_sniffer:
|
||||
@$(PHPCS)
|
||||
|
||||
### - errors filtered by coding standard: PEAR, PSR1, PSR2, Zend...
|
||||
PHPCS_%:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200 --standard=$*
|
||||
@$(PHPCS) --report-full --report-width=200 --standard=$*
|
||||
|
||||
### - errors by Git author
|
||||
code_sniffer_blame:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-gitblame
|
||||
@$(PHPCS) --report-gitblame
|
||||
|
||||
### - all errors/warnings
|
||||
code_sniffer_full:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-full --report-width=200
|
||||
@$(PHPCS) --report-full --report-width=200
|
||||
|
||||
### - errors grouped by kind
|
||||
code_sniffer_source:
|
||||
@$(BIN)/phpcs $(PHP_SOURCE) --report-source || exit 0
|
||||
|
||||
##
|
||||
# PHP Copy/Paste Detector
|
||||
# Detects code redundancy
|
||||
# Documentation: https://github.com/sebastianbergmann/phpcpd
|
||||
##
|
||||
|
||||
copy_paste:
|
||||
@echo "-----------------------"
|
||||
@echo "PHP COPY/PASTE DETECTOR"
|
||||
@echo "-----------------------"
|
||||
@$(BIN)/phpcpd $(PHP_SOURCE) || exit 0
|
||||
@echo
|
||||
|
||||
##
|
||||
# PHP Mess Detector
|
||||
# Detects PHP syntax errors, sorted by category
|
||||
# Rules documentation: http://phpmd.org/rules/index.html
|
||||
##
|
||||
MESS_DETECTOR_RULES = cleancode,codesize,controversial,design,naming,unusedcode
|
||||
|
||||
mess_title:
|
||||
@echo "-----------------"
|
||||
@echo "PHP MESS DETECTOR"
|
||||
@echo "-----------------"
|
||||
|
||||
### - all warnings
|
||||
mess_detector: mess_title
|
||||
@$(BIN)/phpmd $(PHP_COMMA_SOURCE) text $(MESS_DETECTOR_RULES) | sed 's_.*\/__'
|
||||
|
||||
### - all warnings + HTML output contains links to PHPMD's documentation
|
||||
mess_detector_html:
|
||||
@$(BIN)/phpmd $(PHP_COMMA_SOURCE) html $(MESS_DETECTOR_RULES) \
|
||||
--reportfile phpmd.html || exit 0
|
||||
|
||||
### - warnings grouped by message, sorted by descending frequency order
|
||||
mess_detector_grouped: mess_title
|
||||
@$(BIN)/phpmd $(PHP_SOURCE) text $(MESS_DETECTOR_RULES) \
|
||||
| cut -f 2 | sort | uniq -c | sort -nr
|
||||
|
||||
### - summary: number of warnings by rule set
|
||||
mess_detector_summary: mess_title
|
||||
@for rule in $$(echo $(MESS_DETECTOR_RULES) | tr ',' ' '); do \
|
||||
warnings=$$($(BIN)/phpmd $(PHP_COMMA_SOURCE) text $$rule | wc -l); \
|
||||
printf "$$warnings\t$$rule\n"; \
|
||||
done;
|
||||
@$(PHPCS) --report-source || exit 0
|
||||
|
||||
##
|
||||
# Checks source file & script permissions
|
||||
|
|
|
@ -24,7 +24,7 @@ class ApplicationUtils
|
|||
*
|
||||
* @return mixed the version code from the repository if available, else 'false'
|
||||
*/
|
||||
public static function getLatestGitVersionCode($url, $timeout=2)
|
||||
public static function getLatestGitVersionCode($url, $timeout = 2)
|
||||
{
|
||||
list($headers, $data) = get_http_response($url, $timeout);
|
||||
|
||||
|
@ -86,13 +86,14 @@ public static function getVersion($remote, $timeout = 2)
|
|||
*
|
||||
* @return mixed the new version code if available and greater, else 'false'
|
||||
*/
|
||||
public static function checkUpdate($currentVersion,
|
||||
$updateFile,
|
||||
$checkInterval,
|
||||
$enableCheck,
|
||||
$isLoggedIn,
|
||||
$branch='stable')
|
||||
{
|
||||
public static function checkUpdate(
|
||||
$currentVersion,
|
||||
$updateFile,
|
||||
$checkInterval,
|
||||
$enableCheck,
|
||||
$isLoggedIn,
|
||||
$branch = 'stable'
|
||||
) {
|
||||
// Do not check versions for visitors
|
||||
// Do not check if the user doesn't want to
|
||||
// Do not check with dev version
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli;
|
||||
|
||||
|
||||
/**
|
||||
* URL-safe Base64 operations
|
||||
*
|
||||
|
@ -17,7 +16,8 @@ class Base64Url
|
|||
*
|
||||
* @return string Base64Url-encoded data
|
||||
*/
|
||||
public static function encode($data) {
|
||||
public static function encode($data)
|
||||
{
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,8 @@ public static function encode($data) {
|
|||
*
|
||||
* @return string Decoded data
|
||||
*/
|
||||
public static function decode($data) {
|
||||
public static function decode($data)
|
||||
{
|
||||
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,8 @@ protected function buildItem($link, $pageaddr)
|
|||
$upDate = $link['updated'];
|
||||
$link['up_iso_date'] = $this->getIsoDate($upDate, DateTime::ATOM);
|
||||
} else {
|
||||
$link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);;
|
||||
$link['up_iso_date'] = $this->getIsoDate($pubDate, DateTime::ATOM);
|
||||
;
|
||||
}
|
||||
|
||||
// Save the more recent item.
|
||||
|
@ -261,7 +262,6 @@ protected function getIsoDate(DateTime $date, $format = false)
|
|||
}
|
||||
if ($this->feedType == self::$FEED_RSS) {
|
||||
return $date->format(DateTime::RSS);
|
||||
|
||||
}
|
||||
return $date->format(DateTime::ATOM);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
* @param int $timeout network timeout (in seconds)
|
||||
* @param int $maxBytes maximum downloaded bytes (default: 4 MiB)
|
||||
* @param callable|string $curlWriteFunction Optional callback called during the download (cURL CURLOPT_WRITEFUNCTION).
|
||||
* Can be used to add download conditions on the headers (response code, content type, etc.).
|
||||
* Can be used to add download conditions on the
|
||||
* headers (response code, content type, etc.).
|
||||
*
|
||||
* @return array HTTP response headers, downloaded content
|
||||
*
|
||||
|
@ -64,29 +65,30 @@ function get_http_response($url, $timeout = 30, $maxBytes = 4194304, $curlWriteF
|
|||
}
|
||||
|
||||
// General cURL settings
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt(
|
||||
$ch,
|
||||
CURLOPT_HTTPHEADER,
|
||||
array('Accept-Language: ' . $acceptLanguage)
|
||||
);
|
||||
curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRedirs);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
|
||||
curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRedirs);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
|
||||
|
||||
if (is_callable($curlWriteFunction)) {
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $curlWriteFunction);
|
||||
}
|
||||
|
||||
// Max download size management
|
||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024*16);
|
||||
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
|
||||
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION,
|
||||
function($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes)
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024*16);
|
||||
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
|
||||
curl_setopt(
|
||||
$ch,
|
||||
CURLOPT_PROGRESSFUNCTION,
|
||||
function ($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes) {
|
||||
if (version_compare(phpversion(), '5.5', '<')) {
|
||||
// PHP version lower than 5.5
|
||||
// Callback has 4 arguments
|
||||
|
@ -232,7 +234,6 @@ function get_redirected_headers($url, $redirectionLimit = 3)
|
|||
&& !empty($headers)
|
||||
&& (strpos($headers[0], '301') !== false || strpos($headers[0], '302') !== false)
|
||||
&& !empty($headers['Location'])) {
|
||||
|
||||
$redirection = is_array($headers['Location']) ? end($headers['Location']) : $headers['Location'];
|
||||
if ($redirection != $url) {
|
||||
$redirection = getAbsoluteUrl($url, $redirection);
|
||||
|
|
|
@ -92,7 +92,7 @@ public function __construct($language, $conf)
|
|||
/**
|
||||
* Initialize the translator using php gettext extension (gettext dependency act as a wrapper).
|
||||
*/
|
||||
protected function initGettextTranslator ()
|
||||
protected function initGettextTranslator()
|
||||
{
|
||||
$this->translator = new GettextTranslator();
|
||||
$this->translator->setLanguage($this->language);
|
||||
|
@ -125,7 +125,8 @@ protected function initPhpTranslator()
|
|||
$translations = $translations->addFromPoFile('inc/languages/'. $this->language .'/LC_MESSAGES/shaarli.po');
|
||||
$translations->setDomain('shaarli');
|
||||
$this->translator->loadTranslations($translations);
|
||||
} catch (\InvalidArgumentException $e) {}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
|
||||
// Default extension translation from the current theme
|
||||
$theme = $this->conf->get('theme');
|
||||
|
@ -137,7 +138,8 @@ protected function initPhpTranslator()
|
|||
);
|
||||
$translations->setDomain($theme);
|
||||
$this->translator->loadTranslations($translations);
|
||||
} catch (\InvalidArgumentException $e) {}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Extension translations (plugins, themes, etc.).
|
||||
|
@ -147,10 +149,13 @@ protected function initPhpTranslator()
|
|||
}
|
||||
|
||||
try {
|
||||
$extension = Translations::fromPoFile($translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po');
|
||||
$extension = Translations::fromPoFile(
|
||||
$translationPath . $this->language .'/LC_MESSAGES/'. $domain .'.po'
|
||||
);
|
||||
$extension->setDomain($domain);
|
||||
$this->translator->loadTranslations($extension);
|
||||
} catch (\InvalidArgumentException $e) {}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,8 +107,7 @@ public function __construct(
|
|||
$hidePublicLinks,
|
||||
$redirector = '',
|
||||
$redirectorEncode = true
|
||||
)
|
||||
{
|
||||
) {
|
||||
$this->datastore = $datastore;
|
||||
$this->loggedIn = $isLoggedIn;
|
||||
$this->hidePublicLinks = $hidePublicLinks;
|
||||
|
@ -250,11 +249,14 @@ private function check()
|
|||
'id' => 1,
|
||||
'title'=> t('The personal, minimalist, super-fast, database free, bookmarking service'),
|
||||
'url'=>'https://shaarli.readthedocs.io',
|
||||
'description'=>t('Welcome to Shaarli! This is your first public bookmark. To edit or delete me, you must first login.
|
||||
'description'=>t(
|
||||
'Welcome to Shaarli! This is your first public bookmark. '
|
||||
.'To edit or delete me, you must first login.
|
||||
|
||||
To learn how to use Shaarli, consult the link "Documentation" at the bottom of this page.
|
||||
|
||||
You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'),
|
||||
You use the community supported version of the original Shaarli project, by Sebastien Sauvage.'
|
||||
),
|
||||
'private'=>0,
|
||||
'created'=> new DateTime(),
|
||||
'tags'=>'opensource software'
|
||||
|
@ -317,8 +319,7 @@ private function read()
|
|||
} else {
|
||||
$link['real_url'] .= $link['url'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$link['real_url'] = $link['url'];
|
||||
}
|
||||
|
||||
|
@ -403,7 +404,8 @@ public function filterHash($request)
|
|||
*
|
||||
* @return array list of shaare found.
|
||||
*/
|
||||
public function filterDay($request) {
|
||||
public function filterDay($request)
|
||||
{
|
||||
$linkFilter = new LinkFilter($this->links);
|
||||
return $linkFilter->filter(LinkFilter::$FILTER_DAY, $request);
|
||||
}
|
||||
|
@ -420,8 +422,12 @@ public function filterDay($request) {
|
|||
*
|
||||
* @return array filtered links, all links if no suitable filter was provided.
|
||||
*/
|
||||
public function filterSearch($filterRequest = array(), $casesensitive = false, $visibility = 'all', $untaggedonly = false)
|
||||
{
|
||||
public function filterSearch(
|
||||
$filterRequest = array(),
|
||||
$casesensitive = false,
|
||||
$visibility = 'all',
|
||||
$untaggedonly = false
|
||||
) {
|
||||
// Filter link database according to parameters.
|
||||
$searchtags = isset($filterRequest['searchtags']) ? escape($filterRequest['searchtags']) : '';
|
||||
$searchterm = isset($filterRequest['searchterm']) ? escape($filterRequest['searchterm']) : '';
|
||||
|
@ -492,8 +498,7 @@ public function renameTag($from, $to)
|
|||
$delete = empty($to);
|
||||
// True for case-sensitive tag search.
|
||||
$linksToAlter = $this->filterSearch(['searchtags' => $from], true);
|
||||
foreach($linksToAlter as $key => &$value)
|
||||
{
|
||||
foreach ($linksToAlter as $key => &$value) {
|
||||
$tags = preg_split('/\s+/', trim($value['tags']));
|
||||
if (($pos = array_search($from, $tags)) !== false) {
|
||||
if ($delete) {
|
||||
|
@ -536,7 +541,7 @@ public function reorder($order = 'DESC')
|
|||
{
|
||||
$order = $order === 'ASC' ? -1 : 1;
|
||||
// Reorder array by dates.
|
||||
usort($this->links, function($a, $b) use ($order) {
|
||||
usort($this->links, function ($a, $b) use ($order) {
|
||||
if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
|
||||
return $a['sticky'] ? -1 : 1;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public function filter($type, $request, $casesensitive = false, $visibility = 'a
|
|||
$visibility = 'all';
|
||||
}
|
||||
|
||||
switch($type) {
|
||||
switch ($type) {
|
||||
case self::$FILTER_HASH:
|
||||
return $this->filterSmallHash($request);
|
||||
case self::$FILTER_TAG | self::$FILTER_TEXT: // == "vuotext"
|
||||
|
@ -205,7 +205,6 @@ private function filterFulltext($searchterms, $visibility = 'all')
|
|||
|
||||
// Iterate over every stored link.
|
||||
foreach ($this->links as $id => $link) {
|
||||
|
||||
// ignore non private links when 'privatonly' is on.
|
||||
if ($visibility !== 'all') {
|
||||
if (! $link['private'] && $visibility === 'private') {
|
||||
|
@ -257,11 +256,11 @@ private function filterFulltext($searchterms, $visibility = 'all')
|
|||
private static function tag2regex($tag)
|
||||
{
|
||||
$len = strlen($tag);
|
||||
if(!$len || $tag === "-" || $tag === "*"){
|
||||
if (!$len || $tag === "-" || $tag === "*") {
|
||||
// nothing to search, return empty regex
|
||||
return '';
|
||||
}
|
||||
if($tag[0] === "-") {
|
||||
if ($tag[0] === "-") {
|
||||
// query is negated
|
||||
$i = 1; // use offset to start after '-' character
|
||||
$regex = '(?!'; // create negative lookahead
|
||||
|
@ -271,14 +270,14 @@ private static function tag2regex($tag)
|
|||
}
|
||||
$regex .= '.*(?:^| )'; // before tag may only be a space or the beginning
|
||||
// iterate over string, separating it into placeholder and content
|
||||
for(; $i < $len; $i++){
|
||||
if($tag[$i] === '*'){
|
||||
for (; $i < $len; $i++) {
|
||||
if ($tag[$i] === '*') {
|
||||
// placeholder found
|
||||
$regex .= '[^ ]*?';
|
||||
} else {
|
||||
// regular characters
|
||||
$offset = strpos($tag, '*', $i);
|
||||
if($offset === false){
|
||||
if ($offset === false) {
|
||||
// no placeholder found, set offset to end of string
|
||||
$offset = $len;
|
||||
}
|
||||
|
@ -310,19 +309,19 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
|
|||
{
|
||||
// get single tags (we may get passed an array, even though the docs say different)
|
||||
$inputTags = $tags;
|
||||
if(!is_array($tags)) {
|
||||
if (!is_array($tags)) {
|
||||
// we got an input string, split tags
|
||||
$inputTags = preg_split('/(?:\s+)|,/', $inputTags, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
if(!count($inputTags)){
|
||||
if (!count($inputTags)) {
|
||||
// no input tags
|
||||
return $this->noFilter($visibility);
|
||||
}
|
||||
|
||||
// build regex from all tags
|
||||
$re = '/^' . implode(array_map("self::tag2regex", $inputTags)) . '.*$/';
|
||||
if(!$casesensitive) {
|
||||
if (!$casesensitive) {
|
||||
// make regex case insensitive
|
||||
$re .= 'i';
|
||||
}
|
||||
|
@ -342,7 +341,7 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
|
|||
}
|
||||
}
|
||||
$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
|
||||
$descTags = array();
|
||||
// find all tags in the form of #tag in the description
|
||||
|
@ -351,13 +350,13 @@ public function filterTags($tags, $casesensitive = false, $visibility = 'all')
|
|||
$link['description'],
|
||||
$descTags
|
||||
);
|
||||
if(count($descTags[1])){
|
||||
if (count($descTags[1])) {
|
||||
// there were some tags in the description, add them to the search string
|
||||
$search .= ' ' . implode(' ', $descTags[1]);
|
||||
}
|
||||
};
|
||||
// match regular expression with search string
|
||||
if(!preg_match($re, $search)){
|
||||
if (!preg_match($re, $search)) {
|
||||
// this entry does _not_ match our regex
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ function get_curl_download_callback(&$charset, &$title, $curlGetInfo = 'curl_get
|
|||
*
|
||||
* @return int|bool length of $data or false if we need to stop the download
|
||||
*/
|
||||
return function(&$ch, $data) use ($curlGetInfo, &$charset, &$title, &$isRedirected) {
|
||||
return function (&$ch, $data) use ($curlGetInfo, &$charset, &$title, &$isRedirected) {
|
||||
$responseCode = $curlGetInfo($ch, CURLINFO_RESPONSE_CODE);
|
||||
if (!empty($responseCode) && in_array($responseCode, [301, 302])) {
|
||||
$isRedirected = true;
|
||||
|
@ -201,7 +201,8 @@ function space2nbsp($text)
|
|||
|
||||
* @return string formatted description.
|
||||
*/
|
||||
function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '') {
|
||||
function format_description($description, $redirector = '', $urlEncode = true, $indexUrl = '')
|
||||
{
|
||||
return nl2br(space2nbsp(hashtag_autolink(text2clickable($description, $redirector, $urlEncode), $indexUrl)));
|
||||
}
|
||||
|
||||
|
|
|
@ -72,18 +72,20 @@ public static function filterAndFormat($linkDb, $selection, $prependNoteUrl, $in
|
|||
private static function importStatus(
|
||||
$filename,
|
||||
$filesize,
|
||||
$importCount=0,
|
||||
$overwriteCount=0,
|
||||
$skipCount=0,
|
||||
$duration=0
|
||||
)
|
||||
{
|
||||
$importCount = 0,
|
||||
$overwriteCount = 0,
|
||||
$skipCount = 0,
|
||||
$duration = 0
|
||||
) {
|
||||
$status = sprintf(t('File %s (%d bytes) '), $filename, $filesize);
|
||||
if ($importCount == 0 && $overwriteCount == 0 && $skipCount == 0) {
|
||||
$status .= t('has an unknown file format. Nothing was imported.');
|
||||
} else {
|
||||
$status .= vsprintf(
|
||||
t('was successfully processed in %d seconds: %d links imported, %d links overwritten, %d links skipped.'),
|
||||
t(
|
||||
'was successfully processed in %d seconds: '
|
||||
.'%d links imported, %d links overwritten, %d links skipped.'
|
||||
),
|
||||
[$duration, $importCount, $overwriteCount, $skipCount]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ private function initialize()
|
|||
);
|
||||
$this->tpl->assign('newVersion', escape($version));
|
||||
$this->tpl->assign('versionError', '');
|
||||
|
||||
} catch (Exception $exc) {
|
||||
logm($this->conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], $exc->getMessage());
|
||||
$this->tpl->assign('newVersion', '');
|
||||
|
@ -163,7 +162,7 @@ public function assignAll($data)
|
|||
$this->initialize();
|
||||
}
|
||||
|
||||
if (empty($data) || !is_array($data)){
|
||||
if (empty($data) || !is_array($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,8 +75,7 @@ public function load($authorizedPlugins)
|
|||
|
||||
try {
|
||||
$this->loadPlugin($dirs[$index], $plugin);
|
||||
}
|
||||
catch (PluginFileNotFoundException $e) {
|
||||
} catch (PluginFileNotFoundException $e) {
|
||||
error_log($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,10 @@ public function __construct($conf)
|
|||
$this->conf->set('thumbnails.enabled', false);
|
||||
$this->conf->write(true);
|
||||
// TODO: create a proper error handling system able to catch exceptions...
|
||||
die(t('php-gd extension must be loaded to use thumbnails. Thumbnails are now disabled. Please reload the page.'));
|
||||
die(t(
|
||||
'php-gd extension must be loaded to use thumbnails. '
|
||||
.'Thumbnails are now disabled. Please reload the page.'
|
||||
));
|
||||
}
|
||||
|
||||
$this->wt = new WebThumbnailer();
|
||||
|
|
|
@ -183,7 +183,7 @@ public function updateMethodConfigToJson()
|
|||
}
|
||||
}
|
||||
|
||||
try{
|
||||
try {
|
||||
$this->conf->write($this->isLoggedIn);
|
||||
return true;
|
||||
} catch (IOException $e) {
|
||||
|
|
|
@ -34,8 +34,8 @@ function unparse_url($parsedUrl)
|
|||
*/
|
||||
function cleanup_url($url)
|
||||
{
|
||||
$obj_url = new Url($url);
|
||||
return $obj_url->cleanup();
|
||||
$obj_url = new Url($url);
|
||||
return $obj_url->cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,8 +47,8 @@ function cleanup_url($url)
|
|||
*/
|
||||
function get_url_scheme($url)
|
||||
{
|
||||
$obj_url = new Url($url);
|
||||
return $obj_url->getScheme();
|
||||
$obj_url = new Url($url);
|
||||
return $obj_url->getScheme();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,7 +269,8 @@ public function idnToAscii()
|
|||
*
|
||||
* @return string the URL scheme or false if none is provided.
|
||||
*/
|
||||
public function getScheme() {
|
||||
public function getScheme()
|
||||
{
|
||||
if (!isset($this->parts['scheme'])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -281,7 +282,8 @@ public function getScheme() {
|
|||
*
|
||||
* @return string the URL host or false if none is provided.
|
||||
*/
|
||||
public function getHost() {
|
||||
public function getHost()
|
||||
{
|
||||
if (empty($this->parts['host'])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -293,7 +295,8 @@ public function getHost() {
|
|||
*
|
||||
* @return true is HTTP, false otherwise.
|
||||
*/
|
||||
public function isHttp() {
|
||||
public function isHttp()
|
||||
{
|
||||
return strpos(strtolower($this->parts['scheme']), 'http') !== false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ function escape($input)
|
|||
|
||||
if (is_array($input)) {
|
||||
$out = array();
|
||||
foreach($input as $key => $value) {
|
||||
foreach ($input as $key => $value) {
|
||||
$out[$key] = escape($value);
|
||||
}
|
||||
return $out;
|
||||
|
@ -355,10 +355,13 @@ function return_bytes($val)
|
|||
$val = trim($val);
|
||||
$last = strtolower($val[strlen($val)-1]);
|
||||
$val = intval(substr($val, 0, -1));
|
||||
switch($last) {
|
||||
case 'g': $val *= 1024;
|
||||
case 'm': $val *= 1024;
|
||||
case 'k': $val *= 1024;
|
||||
switch ($last) {
|
||||
case 'g':
|
||||
$val *= 1024;
|
||||
case 'm':
|
||||
$val *= 1024;
|
||||
case 'k':
|
||||
$val *= 1024;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
@ -452,6 +455,7 @@ function alphabetical_sort(&$data, $reverse = false, $byKeys = false)
|
|||
*
|
||||
* @return string Text translated.
|
||||
*/
|
||||
function t($text, $nText = '', $nb = 1, $domain = 'shaarli') {
|
||||
function t($text, $nText = '', $nb = 1, $domain = 'shaarli')
|
||||
{
|
||||
return dn__($domain, $text, $nText, $nb);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public function __invoke($request, $response, $next)
|
|||
try {
|
||||
$this->checkRequest($request);
|
||||
$response = $next($request, $response);
|
||||
} catch(ApiException $e) {
|
||||
} catch (ApiException $e) {
|
||||
$e->setResponse($response);
|
||||
$e->setDebug($this->conf->get('dev.debug', false));
|
||||
$response = $e->getApiResponse();
|
||||
|
@ -98,7 +98,8 @@ protected function checkRequest($request)
|
|||
*
|
||||
* @throws ApiAuthorizationException The token couldn't be validated.
|
||||
*/
|
||||
protected function checkToken($request) {
|
||||
protected function checkToken($request)
|
||||
{
|
||||
if (! $request->hasHeader('Authorization')) {
|
||||
throw new ApiAuthorizationException('JWT token not provided');
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ public function getHistory($request, $response)
|
|||
$offset = $request->getParam('offset');
|
||||
if (empty($offset)) {
|
||||
$offset = 0;
|
||||
}
|
||||
elseif (ctype_digit($offset)) {
|
||||
} elseif (ctype_digit($offset)) {
|
||||
$offset = (int) $offset;
|
||||
} else {
|
||||
throw new ApiBadParametersException('Invalid offset');
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
* Parent Exception related to the API, able to generate a valid Response (ResponseInterface).
|
||||
* Also can include various information in debug mode.
|
||||
*/
|
||||
abstract class ApiException extends \Exception {
|
||||
abstract class ApiException extends \Exception
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Response instance from Slim.
|
||||
|
@ -27,7 +28,7 @@ abstract class ApiException extends \Exception {
|
|||
*
|
||||
* @return Response Final response to give.
|
||||
*/
|
||||
public abstract function getApiResponse();
|
||||
abstract public function getApiResponse();
|
||||
|
||||
/**
|
||||
* Creates ApiResponse body.
|
||||
|
@ -36,7 +37,8 @@ public abstract function getApiResponse();
|
|||
*
|
||||
* @return array|string response body
|
||||
*/
|
||||
protected function getApiResponseBody() {
|
||||
protected function getApiResponseBody()
|
||||
{
|
||||
if ($this->debug !== true) {
|
||||
return $this->getMessage();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli\Api\Exceptions;
|
||||
|
||||
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli\Api\Exceptions;
|
||||
|
||||
|
||||
use Slim\Http\Response;
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,12 +104,20 @@ public function write($filepath, $conf)
|
|||
|
||||
// Store all $conf['config']
|
||||
foreach ($conf['config'] as $key => $value) {
|
||||
$configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($conf['config'][$key], true).';'. PHP_EOL;
|
||||
$configStr .= '$GLOBALS[\'config\'][\''
|
||||
. $key
|
||||
.'\'] = '
|
||||
.var_export($conf['config'][$key], true).';'
|
||||
. PHP_EOL;
|
||||
}
|
||||
|
||||
if (isset($conf['plugins'])) {
|
||||
foreach ($conf['plugins'] as $key => $value) {
|
||||
$configStr .= '$GLOBALS[\'plugins\'][\''. $key .'\'] = '.var_export($conf['plugins'][$key], true).';'. PHP_EOL;
|
||||
$configStr .= '$GLOBALS[\'plugins\'][\''
|
||||
. $key
|
||||
.'\'] = '
|
||||
.var_export($conf['plugins'][$key], true).';'
|
||||
. PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ function save_plugin_config($formData)
|
|||
// If there is no order, it means a disabled plugin has been enabled.
|
||||
if (isset($formData['order_' . $key])) {
|
||||
$plugins[(int) $formData['order_' . $key]] = $key;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$newEnabledPlugins[] = $key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,6 @@ public function checkLoginState($cookie, $clientIpId)
|
|||
// The user client has a valid stay-signed-in cookie
|
||||
// Session information is updated with the current client information
|
||||
$this->sessionManager->storeLoginInfo($clientIpId);
|
||||
|
||||
} elseif ($this->sessionManager->hasSessionExpired()
|
||||
|| $this->sessionManager->hasClientIpChanged($clientIpId)
|
||||
) {
|
||||
|
|
|
@ -24,11 +24,9 @@
|
|||
"gettext/gettext": "^4.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpmd/phpmd" : "@stable",
|
||||
"phpunit/phpcov": "*",
|
||||
"phpunit/phpunit": "^5.0",
|
||||
"sebastian/phpcpd": "*",
|
||||
"squizlabs/php_codesniffer": "2.*",
|
||||
"phpunit/phpcov": "*"
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
357
composer.lock
generated
357
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "0dc33ee0b7d9f47868d4fa961f0d13b4",
|
||||
"content-hash": "3876b34296fedb365517b785af8384de",
|
||||
"packages": [
|
||||
{
|
||||
"name": "arthurhoaro/web-thumbnailer",
|
||||
|
@ -593,12 +593,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pubsubhubbub/php-publisher.git",
|
||||
"reference": "e8a7cf52a2c86b0c364da56f7192ec020c83b8f7"
|
||||
"reference": "047b0faf6219071527a45942d6fef4dbc6d1d884"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/e8a7cf52a2c86b0c364da56f7192ec020c83b8f7",
|
||||
"reference": "e8a7cf52a2c86b0c364da56f7192ec020c83b8f7",
|
||||
"url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/047b0faf6219071527a45942d6fef4dbc6d1d884",
|
||||
"reference": "047b0faf6219071527a45942d6fef4dbc6d1d884",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -627,9 +627,10 @@
|
|||
"data",
|
||||
"feeds",
|
||||
"publishers",
|
||||
"pubsubhubbub"
|
||||
"pubsubhubbub",
|
||||
"websub"
|
||||
],
|
||||
"time": "2018-10-05T12:31:04+00:00"
|
||||
"time": "2018-10-09T05:20:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "shaarli/netscape-bookmark-parser",
|
||||
|
@ -858,46 +859,6 @@
|
|||
],
|
||||
"time": "2017-10-19T19:58:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pdepend/pdepend",
|
||||
"version": "2.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pdepend/pdepend.git",
|
||||
"reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pdepend/pdepend/zipball/9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
|
||||
"reference": "9daf26d0368d4a12bed1cacae1a9f3a6f0adf239",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.7",
|
||||
"symfony/config": "^2.3.0|^3|^4",
|
||||
"symfony/dependency-injection": "^2.3.0|^3|^4",
|
||||
"symfony/filesystem": "^2.3.0|^3|^4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8|^5.7",
|
||||
"squizlabs/php_codesniffer": "^2.0.0"
|
||||
},
|
||||
"bin": [
|
||||
"src/bin/pdepend"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PDepend\\": "src/main/php/PDepend"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Official version of pdepend to be handled with Composer",
|
||||
"time": "2017-12-13T13:21:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "1.0.1",
|
||||
|
@ -1044,72 +1005,6 @@
|
|||
],
|
||||
"time": "2017-07-14T14:27:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpmd/phpmd",
|
||||
"version": "2.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpmd/phpmd.git",
|
||||
"reference": "4e9924b2c157a3eb64395460fcf56b31badc8374"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374",
|
||||
"reference": "4e9924b2c157a3eb64395460fcf56b31badc8374",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-xml": "*",
|
||||
"pdepend/pdepend": "^2.5",
|
||||
"php": ">=5.3.9"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^2.0"
|
||||
},
|
||||
"bin": [
|
||||
"src/bin/phpmd"
|
||||
],
|
||||
"type": "project",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"PHPMD\\": "src/main/php"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Manuel Pichler",
|
||||
"email": "github@manuel-pichler.de",
|
||||
"homepage": "https://github.com/manuelpichler",
|
||||
"role": "Project Founder"
|
||||
},
|
||||
{
|
||||
"name": "Other contributors",
|
||||
"homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
|
||||
"role": "Contributors"
|
||||
},
|
||||
{
|
||||
"name": "Marc Würth",
|
||||
"email": "ravage@bluewin.ch",
|
||||
"homepage": "https://github.com/ravage84",
|
||||
"role": "Project Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.",
|
||||
"homepage": "http://phpmd.org/",
|
||||
"keywords": [
|
||||
"mess detection",
|
||||
"mess detector",
|
||||
"pdepend",
|
||||
"phpmd",
|
||||
"pmd"
|
||||
],
|
||||
"time": "2017-01-20T14:41:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "1.8.0",
|
||||
|
@ -1988,56 +1883,6 @@
|
|||
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
||||
"time": "2017-02-18T15:18:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/phpcpd",
|
||||
"version": "3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpcpd.git",
|
||||
"reference": "dfed51c1288790fc957c9433e2f49ab152e8a564"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/dfed51c1288790fc957c9433e2f49ab152e8a564",
|
||||
"reference": "dfed51c1288790fc957c9433e2f49ab152e8a564",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6|^7.0",
|
||||
"phpunit/php-timer": "^1.0.6",
|
||||
"sebastian/finder-facade": "^1.1",
|
||||
"sebastian/version": "^1.0|^2.0",
|
||||
"symfony/console": "^2.7|^3.0|^4.0"
|
||||
},
|
||||
"bin": [
|
||||
"phpcpd"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Copy/Paste Detector (CPD) for PHP code.",
|
||||
"homepage": "https://github.com/sebastianbergmann/phpcpd",
|
||||
"time": "2017-11-16T08:49:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/recursion-context",
|
||||
"version": "2.0.0",
|
||||
|
@ -2254,70 +2099,6 @@
|
|||
],
|
||||
"time": "2017-05-22T02:43:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "e5389132dc6320682de3643091121c048ff796b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/e5389132dc6320682de3643091121c048ff796b3",
|
||||
"reference": "e5389132dc6320682de3643091121c048ff796b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/filesystem": "~2.8|~3.0|~4.0",
|
||||
"symfony/polyfill-ctype": "~1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.3",
|
||||
"symfony/finder": "<3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dependency-injection": "~3.3|~4.0",
|
||||
"symfony/event-dispatcher": "~3.3|~4.0",
|
||||
"symfony/finder": "~3.3|~4.0",
|
||||
"symfony/yaml": "~3.0|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "To use the yaml reference dumper"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Config\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Config Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-09-08T13:15:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v3.4.17",
|
||||
|
@ -2443,127 +2224,6 @@
|
|||
"homepage": "https://symfony.com",
|
||||
"time": "2018-10-02T16:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dependency-injection",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dependency-injection.git",
|
||||
"reference": "aea20fef4e92396928b5db175788b90234c0270d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/aea20fef4e92396928b5db175788b90234c0270d",
|
||||
"reference": "aea20fef4e92396928b5db175788b90234c0270d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<3.3.7",
|
||||
"symfony/finder": "<3.3",
|
||||
"symfony/proxy-manager-bridge": "<3.4",
|
||||
"symfony/yaml": "<3.4"
|
||||
},
|
||||
"provide": {
|
||||
"psr/container-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/config": "~3.3|~4.0",
|
||||
"symfony/expression-language": "~2.8|~3.0|~4.0",
|
||||
"symfony/yaml": "~3.4|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/config": "",
|
||||
"symfony/expression-language": "For using expressions in service container configuration",
|
||||
"symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
|
||||
"symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\DependencyInjection\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony DependencyInjection Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-10-02T12:28:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v3.4.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "d69930fc337d767607267d57c20a7403d0a822a4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d69930fc337d767607267d57c20a7403d0a822a4",
|
||||
"reference": "d69930fc337d767607267d57c20a7403d0a822a4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/polyfill-ctype": "~1.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Filesystem\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-10-02T12:28:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v3.4.17",
|
||||
|
@ -2883,8 +2543,7 @@
|
|||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"pubsubhubbub/publisher": 20,
|
||||
"phpmd/phpmd": 0
|
||||
"pubsubhubbub/publisher": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
|
|
278
index.php
278
index.php
|
@ -28,7 +28,7 @@
|
|||
define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0)));
|
||||
|
||||
// High execution time in case of problematic imports/exports.
|
||||
ini_set('max_input_time','60');
|
||||
ini_set('max_input_time', '60');
|
||||
|
||||
// Try to set max upload file size and read
|
||||
ini_set('memory_limit', '128M');
|
||||
|
@ -85,7 +85,7 @@
|
|||
// Ensure the PHP version is supported
|
||||
try {
|
||||
ApplicationUtils::checkPHPVersion('5.5', PHP_VERSION);
|
||||
} catch(Exception $exc) {
|
||||
} catch (Exception $exc) {
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
echo $exc->getMessage();
|
||||
exit;
|
||||
|
@ -223,7 +223,6 @@ function isLoggedIn()
|
|||
$expirationTime,
|
||||
WEB_PATH
|
||||
);
|
||||
|
||||
} else {
|
||||
// Standard session expiration (=when browser closes)
|
||||
$expirationTime = 0;
|
||||
|
@ -257,7 +256,8 @@ function isLoggedIn()
|
|||
exit;
|
||||
}
|
||||
}
|
||||
header('Location: ?'); exit;
|
||||
header('Location: ?');
|
||||
exit;
|
||||
} else {
|
||||
$loginManager->handleFailedLogin($_SERVER);
|
||||
$redir = '&username='. urlencode($_POST['login']);
|
||||
|
@ -278,7 +278,9 @@ function isLoggedIn()
|
|||
// ------------------------------------------------------------------------------------------
|
||||
// Token management for XSRF protection
|
||||
// Token should be used in any form which acts on data (create,update,delete,import...).
|
||||
if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are attached to the session.
|
||||
if (!isset($_SESSION['tokens'])) {
|
||||
$_SESSION['tokens']=array(); // Token are attached to the session.
|
||||
}
|
||||
|
||||
/**
|
||||
* Daily RSS feed: 1 RSS entry per day giving all the links on that day.
|
||||
|
@ -288,13 +290,14 @@ function isLoggedIn()
|
|||
* @param ConfigManager $conf Configuration Manager instance
|
||||
* @param LoginManager $loginManager LoginManager instance
|
||||
*/
|
||||
function showDailyRSS($conf, $loginManager) {
|
||||
function showDailyRSS($conf, $loginManager)
|
||||
{
|
||||
// Cache system
|
||||
$query = $_SERVER['QUERY_STRING'];
|
||||
$cache = new CachedPage(
|
||||
$conf->get('config.PAGE_CACHE'),
|
||||
page_url($_SERVER),
|
||||
startsWith($query,'do=dailyrss') && !$loginManager->isLoggedIn()
|
||||
startsWith($query, 'do=dailyrss') && !$loginManager->isLoggedIn()
|
||||
);
|
||||
$cached = $cache->cachedVersion();
|
||||
if (!empty($cached)) {
|
||||
|
@ -395,7 +398,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
{
|
||||
$day = date('Ymd', strtotime('-1 day')); // Yesterday, in format YYYYMMDD.
|
||||
if (isset($_GET['day'])) {
|
||||
$day = $_GET['day'];
|
||||
$day = $_GET['day'];
|
||||
}
|
||||
|
||||
$days = $LINKSDB->days();
|
||||
|
@ -413,7 +416,7 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
$previousday=$days[$i - 1];
|
||||
}
|
||||
if ($i < count($days) - 1) {
|
||||
$nextday = $days[$i + 1];
|
||||
$nextday = $days[$i + 1];
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
@ -424,8 +427,8 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
}
|
||||
|
||||
// We pre-format some fields for proper output.
|
||||
foreach($linksToDisplay as $key => $link) {
|
||||
$taglist = explode(' ',$link['tags']);
|
||||
foreach ($linksToDisplay as $key => $link) {
|
||||
$taglist = explode(' ', $link['tags']);
|
||||
uasort($taglist, 'strcasecmp');
|
||||
$linksToDisplay[$key]['taglist']=$taglist;
|
||||
$linksToDisplay[$key]['formatedDescription'] = format_description(
|
||||
|
@ -457,14 +460,14 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
*/
|
||||
$columns = array(array(), array(), array()); // Entries to display, for each column.
|
||||
$fill = array(0, 0, 0); // Rough estimate of columns fill.
|
||||
foreach($data['linksToDisplay'] as $key => $link) {
|
||||
foreach ($data['linksToDisplay'] as $key => $link) {
|
||||
// Roughly estimate length of entry (by counting characters)
|
||||
// Title: 30 chars = 1 line. 1 line is 30 pixels height.
|
||||
// Description: 836 characters gives roughly 342 pixel height.
|
||||
// This is not perfect, but it's usually OK.
|
||||
$length = strlen($link['title']) + (342 * strlen($link['description'])) / 836;
|
||||
if ($link['thumbnail']) {
|
||||
$length += 100; // 1 thumbnails roughly takes 100 pixels height.
|
||||
$length += 100; // 1 thumbnails roughly takes 100 pixels height.
|
||||
}
|
||||
// Then put in column which is the less filled:
|
||||
$smallest = min($fill); // find smallest value in array.
|
||||
|
@ -492,8 +495,9 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
* @param ConfigManager $conf Configuration Manager instance.
|
||||
* @param PluginManager $pluginManager Plugin Manager instance.
|
||||
*/
|
||||
function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager) {
|
||||
buildLinkList($PAGE,$LINKSDB, $conf, $pluginManager, $loginManager);
|
||||
function showLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
|
||||
{
|
||||
buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager);
|
||||
$PAGE->renderPage('linklist');
|
||||
}
|
||||
|
||||
|
@ -524,8 +528,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$updater->getDoneUpdates()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
|
@ -538,8 +541,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$query = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : '';
|
||||
$targetPage = Router::findPage($query, $_GET, $loginManager->isLoggedIn());
|
||||
|
||||
if (
|
||||
// if the user isn't logged in
|
||||
if (// if the user isn't logged in
|
||||
!$loginManager->isLoggedIn() &&
|
||||
// and Shaarli doesn't have public content...
|
||||
$conf->get('privacy.hide_public_links') &&
|
||||
|
@ -563,9 +565,11 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
'footer',
|
||||
);
|
||||
|
||||
foreach($common_hooks as $name) {
|
||||
foreach ($common_hooks as $name) {
|
||||
$plugin_data = array();
|
||||
$pluginManager->executeHooks('render_' . $name, $plugin_data,
|
||||
$pluginManager->executeHooks(
|
||||
'render_' . $name,
|
||||
$plugin_data,
|
||||
array(
|
||||
'target' => $targetPage,
|
||||
'loggedin' => $loginManager->isLoggedIn()
|
||||
|
@ -575,13 +579,15 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Display login form.
|
||||
if ($targetPage == Router::$PAGE_LOGIN)
|
||||
{
|
||||
if ($conf->get('security.open_shaarli')) { header('Location: ?'); exit; } // No need to login for open Shaarli
|
||||
if ($targetPage == Router::$PAGE_LOGIN) {
|
||||
if ($conf->get('security.open_shaarli')) {
|
||||
header('Location: ?');
|
||||
exit;
|
||||
} // No need to login for open Shaarli
|
||||
if (isset($_GET['username'])) {
|
||||
$PAGE->assign('username', escape($_GET['username']));
|
||||
}
|
||||
$PAGE->assign('returnurl',(isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):''));
|
||||
$PAGE->assign('returnurl', (isset($_SERVER['HTTP_REFERER']) ? escape($_SERVER['HTTP_REFERER']):''));
|
||||
// add default state of the 'remember me' checkbox
|
||||
$PAGE->assign('remember_user_default', $conf->get('privacy.remember_user_default'));
|
||||
$PAGE->assign('user_can_login', $loginManager->canLogin($_SERVER));
|
||||
|
@ -590,8 +596,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
exit;
|
||||
}
|
||||
// -------- User wants to logout.
|
||||
if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout'))
|
||||
{
|
||||
if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout')) {
|
||||
invalidateCaches($conf->get('resource.page_cache'));
|
||||
$sessionManager->logout();
|
||||
setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, 'false', 0, WEB_PATH);
|
||||
|
@ -600,8 +605,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Picture wall
|
||||
if ($targetPage == Router::$PAGE_PICWALL)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_PICWALL) {
|
||||
$PAGE->assign('pagetitle', t('Picture wall') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
if (! $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) === Thumbnailer::MODE_NONE) {
|
||||
$PAGE->assign('linksToDisplay', []);
|
||||
|
@ -615,8 +619,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
|
||||
// Get only links which have a thumbnail.
|
||||
// Note: we do not retrieve thumbnails here, the request is too heavy.
|
||||
foreach($links as $key => $link)
|
||||
{
|
||||
foreach ($links as $key => $link) {
|
||||
if (isset($link['thumbnail']) && $link['thumbnail'] !== false) {
|
||||
$linksToDisplay[] = $link; // Add to array.
|
||||
}
|
||||
|
@ -637,8 +640,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Tag cloud
|
||||
if ($targetPage == Router::$PAGE_TAGCLOUD)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_TAGCLOUD) {
|
||||
$visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
|
||||
$filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : [];
|
||||
$tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility);
|
||||
|
@ -653,7 +655,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
alphabetical_sort($tags, false, true);
|
||||
|
||||
$tagList = array();
|
||||
foreach($tags as $key => $value) {
|
||||
foreach ($tags as $key => $value) {
|
||||
if (in_array($key, $filteringTags)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -685,8 +687,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Tag list
|
||||
if ($targetPage == Router::$PAGE_TAGLIST)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_TAGLIST) {
|
||||
$visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '';
|
||||
$filteringTags = isset($_GET['searchtags']) ? explode(' ', $_GET['searchtags']) : [];
|
||||
$tags = $LINKSDB->linksCountPerTag($filteringTags, $visibility);
|
||||
|
@ -732,7 +733,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$cache = new CachedPage(
|
||||
$conf->get('resource.page_cache'),
|
||||
page_url($_SERVER),
|
||||
startsWith($query,'do='. $targetPage) && !$loginManager->isLoggedIn()
|
||||
startsWith($query, 'do='. $targetPage) && !$loginManager->isLoggedIn()
|
||||
);
|
||||
$cached = $cache->cachedVersion();
|
||||
if (!empty($cached)) {
|
||||
|
@ -770,11 +771,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...)
|
||||
if (isset($_GET['addtag']))
|
||||
{
|
||||
if (isset($_GET['addtag'])) {
|
||||
// Get previous URL (http_referer) and add the tag to the searchtags parameters in query.
|
||||
if (empty($_SERVER['HTTP_REFERER'])) { header('Location: ?searchtags='.urlencode($_GET['addtag'])); exit; } // In case browser does not send HTTP_REFERER
|
||||
parse_str(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_QUERY), $params);
|
||||
if (empty($_SERVER['HTTP_REFERER'])) {
|
||||
// In case browser does not send HTTP_REFERER
|
||||
header('Location: ?searchtags='.urlencode($_GET['addtag']));
|
||||
exit;
|
||||
}
|
||||
parse_str(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY), $params);
|
||||
|
||||
// Prevent redirection loop
|
||||
if (isset($params['addtag'])) {
|
||||
|
@ -798,12 +802,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
// Append the tag if necessary
|
||||
if (empty($params['searchtags'])) {
|
||||
$params['searchtags'] = trim($_GET['addtag']);
|
||||
}
|
||||
elseif ($addtag) {
|
||||
} elseif ($addtag) {
|
||||
$params['searchtags'] = trim($params['searchtags']).' '.trim($_GET['addtag']);
|
||||
}
|
||||
|
||||
unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different)
|
||||
// We also remove page (keeping the same page has no sense, since the
|
||||
// results are different)
|
||||
unset($params['page']);
|
||||
|
||||
header('Location: ?'.http_build_query($params));
|
||||
exit;
|
||||
}
|
||||
|
@ -828,13 +834,15 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$tags = explode(' ', $params['searchtags']);
|
||||
// Remove value from array $tags.
|
||||
$tags = array_diff($tags, array($_GET['removetag']));
|
||||
$params['searchtags'] = implode(' ',$tags);
|
||||
$params['searchtags'] = implode(' ', $tags);
|
||||
|
||||
if (empty($params['searchtags'])) {
|
||||
unset($params['searchtags']);
|
||||
}
|
||||
|
||||
unset($params['page']); // We also remove page (keeping the same page has no sense, since the results are different)
|
||||
// We also remove page (keeping the same page has no sense, since
|
||||
// the results are different)
|
||||
unset($params['page']);
|
||||
}
|
||||
header('Location: ?'.http_build_query($params));
|
||||
exit;
|
||||
|
@ -897,12 +905,10 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- Handle other actions allowed for non-logged in users:
|
||||
if (!$loginManager->isLoggedIn())
|
||||
{
|
||||
if (!$loginManager->isLoggedIn()) {
|
||||
// User tries to post new link but is not logged in:
|
||||
// Show login screen, then redirect to ?post=...
|
||||
if (isset($_GET['post']))
|
||||
{
|
||||
if (isset($_GET['post'])) {
|
||||
header( // Redirect to login page, then back to post link.
|
||||
'Location: ?do=login&post='.urlencode($_GET['post']).
|
||||
(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').
|
||||
|
@ -925,8 +931,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
// -------- All other functions are reserved for the registered user:
|
||||
|
||||
// -------- Display the Tools menu if requested (import/export/bookmarklet...)
|
||||
if ($targetPage == Router::$PAGE_TOOLS)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_TOOLS) {
|
||||
$data = [
|
||||
'pageabsaddr' => index_url($_SERVER),
|
||||
'sslenabled' => is_https($_SERVER),
|
||||
|
@ -943,30 +948,40 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to change his/her password.
|
||||
if ($targetPage == Router::$PAGE_CHANGEPASSWORD)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_CHANGEPASSWORD) {
|
||||
if ($conf->get('security.open_shaarli')) {
|
||||
die(t('You are not supposed to change a password on an Open Shaarli.'));
|
||||
}
|
||||
|
||||
if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword']))
|
||||
{
|
||||
if (!$sessionManager->checkToken($_POST['token'])) die(t('Wrong token.')); // Go away!
|
||||
if (!empty($_POST['setpassword']) && !empty($_POST['oldpassword'])) {
|
||||
if (!$sessionManager->checkToken($_POST['token'])) {
|
||||
die(t('Wrong token.')); // Go away!
|
||||
}
|
||||
|
||||
// Make sure old password is correct.
|
||||
$oldhash = sha1($_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt'));
|
||||
if ($oldhash!= $conf->get('credentials.hash')) {
|
||||
echo '<script>alert("'. t('The old password is not correct.') .'");document.location=\'?do=changepasswd\';</script>';
|
||||
$oldhash = sha1(
|
||||
$_POST['oldpassword'].$conf->get('credentials.login').$conf->get('credentials.salt')
|
||||
);
|
||||
if ($oldhash != $conf->get('credentials.hash')) {
|
||||
echo '<script>alert("'
|
||||
. t('The old password is not correct.')
|
||||
.'");document.location=\'?do=changepasswd\';</script>';
|
||||
exit;
|
||||
}
|
||||
// Save new password
|
||||
// Salt renders rainbow-tables attacks useless.
|
||||
$conf->set('credentials.salt', sha1(uniqid('', true) .'_'. mt_rand()));
|
||||
$conf->set('credentials.hash', sha1($_POST['setpassword'] . $conf->get('credentials.login') . $conf->get('credentials.salt')));
|
||||
$conf->set(
|
||||
'credentials.hash',
|
||||
sha1(
|
||||
$_POST['setpassword']
|
||||
. $conf->get('credentials.login')
|
||||
. $conf->get('credentials.salt')
|
||||
)
|
||||
);
|
||||
try {
|
||||
$conf->write($loginManager->isLoggedIn());
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while writing config file after changing password.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
|
@ -978,9 +993,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
echo '<script>alert("'. t('Your password has been changed') .'");document.location=\'?do=tools\';</script>';
|
||||
exit;
|
||||
}
|
||||
else // show the change password form.
|
||||
{
|
||||
} else {
|
||||
// show the change password form.
|
||||
$PAGE->assign('pagetitle', t('Change password') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
$PAGE->renderPage('changepassword');
|
||||
exit;
|
||||
|
@ -988,10 +1002,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to change configuration
|
||||
if ($targetPage == Router::$PAGE_CONFIGURE)
|
||||
{
|
||||
if (!empty($_POST['title']) )
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_CONFIGURE) {
|
||||
if (!empty($_POST['title'])) {
|
||||
if (!$sessionManager->checkToken($_POST['token'])) {
|
||||
die(t('Wrong token.')); // Go away!
|
||||
}
|
||||
|
@ -1019,7 +1031,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
&& $thumbnailsMode !== $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
|
||||
) {
|
||||
$_SESSION['warnings'][] = t(
|
||||
'You have enabled or changed thumbnails mode. <a href="?do=thumbs_update">Please synchronize them</a>.'
|
||||
'You have enabled or changed thumbnails mode. '
|
||||
.'<a href="?do=thumbs_update">Please synchronize them</a>.'
|
||||
);
|
||||
}
|
||||
$conf->set('thumbnails.mode', $thumbnailsMode);
|
||||
|
@ -1028,8 +1041,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$conf->write($loginManager->isLoggedIn());
|
||||
$history->updateSettings();
|
||||
invalidateCaches($conf->get('resource.page_cache'));
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while writing config file after configuration update.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
|
@ -1041,9 +1053,8 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
echo '<script>alert("'. t('Configuration was saved.') .'");document.location=\'?do=configure\';</script>';
|
||||
exit;
|
||||
}
|
||||
else // Show the configuration form.
|
||||
{
|
||||
} else {
|
||||
// Show the configuration form.
|
||||
$PAGE->assign('title', $conf->get('general.title'));
|
||||
$PAGE->assign('theme', $conf->get('resource.theme'));
|
||||
$PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
|
||||
|
@ -1071,8 +1082,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to rename a tag or delete it
|
||||
if ($targetPage == Router::$PAGE_CHANGETAG)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_CHANGETAG) {
|
||||
if (empty($_POST['fromtag']) || (empty($_POST['totag']) && isset($_POST['renametag']))) {
|
||||
$PAGE->assign('fromtag', ! empty($_GET['fromtag']) ? escape($_GET['fromtag']) : '');
|
||||
$PAGE->assign('pagetitle', t('Manage tags') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
|
@ -1101,16 +1111,14 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User wants to add a link without using the bookmarklet: Show form.
|
||||
if ($targetPage == Router::$PAGE_ADDLINK)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_ADDLINK) {
|
||||
$PAGE->assign('pagetitle', t('Shaare a new link') .' - '. $conf->get('general.title', 'Shaarli'));
|
||||
$PAGE->renderPage('addlink');
|
||||
exit;
|
||||
}
|
||||
|
||||
// -------- User clicked the "Save" button when editing a link: Save link to database.
|
||||
if (isset($_POST['save_edit']))
|
||||
{
|
||||
if (isset($_POST['save_edit'])) {
|
||||
// Go away!
|
||||
if (! $sessionManager->checkToken($_POST['token'])) {
|
||||
die(t('Wrong token.'));
|
||||
|
@ -1197,14 +1205,16 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicked the "Cancel" button when editing a link.
|
||||
if (isset($_POST['cancel_edit']))
|
||||
{
|
||||
if (isset($_POST['cancel_edit'])) {
|
||||
$id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false;
|
||||
if (! isset($LINKSDB[$id])) {
|
||||
header('Location: ?');
|
||||
}
|
||||
// If we are called from the bookmarklet, we must close the popup:
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
|
||||
echo '<script>self.close();</script>';
|
||||
exit;
|
||||
}
|
||||
$link = $LINKSDB[$id];
|
||||
$returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' );
|
||||
// Scroll to the link which has been edited.
|
||||
|
@ -1215,8 +1225,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicked the "Delete" button when editing a link: Delete link from database.
|
||||
if ($targetPage == Router::$PAGE_DELETELINK)
|
||||
{
|
||||
if ($targetPage == Router::$PAGE_DELETELINK) {
|
||||
if (! $sessionManager->checkToken($_GET['token'])) {
|
||||
die(t('Wrong token.'));
|
||||
}
|
||||
|
@ -1230,7 +1239,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$ids = [$ids];
|
||||
}
|
||||
// assert at least one id is given
|
||||
if(!count($ids)){
|
||||
if (!count($ids)) {
|
||||
die('no id provided');
|
||||
}
|
||||
foreach ($ids as $id) {
|
||||
|
@ -1243,15 +1252,18 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$LINKSDB->save($conf->get('resource.page_cache')); // save to disk
|
||||
|
||||
// If we are called from the bookmarklet, we must close the popup:
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; }
|
||||
if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) {
|
||||
echo '<script>self.close();</script>';
|
||||
exit;
|
||||
}
|
||||
|
||||
$location = '?';
|
||||
if (isset($_SERVER['HTTP_REFERER'])) {
|
||||
// Don't redirect to where we were previously if it was a permalink or an edit_link, because it would 404.
|
||||
$location = generateLocation(
|
||||
$_SERVER['HTTP_REFERER'],
|
||||
$_SERVER['HTTP_HOST'],
|
||||
['delete_link', 'edit_link', $link['shorturl']]
|
||||
$_SERVER['HTTP_REFERER'],
|
||||
$_SERVER['HTTP_HOST'],
|
||||
['delete_link', 'edit_link', $link['shorturl']]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1260,11 +1272,13 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
}
|
||||
|
||||
// -------- User clicked the "EDIT" button on a link: Display link edit form.
|
||||
if (isset($_GET['edit_link']))
|
||||
{
|
||||
if (isset($_GET['edit_link'])) {
|
||||
$id = (int) escape($_GET['edit_link']);
|
||||
$link = $LINKSDB[$id]; // Read database
|
||||
if (!$link) { header('Location: ?'); exit; } // Link not found in database.
|
||||
if (!$link) {
|
||||
header('Location: ?');
|
||||
exit;
|
||||
} // Link not found in database.
|
||||
$link['linkdate'] = $link['created']->format(LinkDB::LINK_DATE_FORMAT);
|
||||
$data = array(
|
||||
'link' => $link,
|
||||
|
@ -1290,8 +1304,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$link_is_new = false;
|
||||
// Check if URL is not already in database (in this case, we will edit the existing link)
|
||||
$link = $LINKSDB->getLinkFromUrl($url);
|
||||
if (! $link)
|
||||
{
|
||||
if (! $link) {
|
||||
$link_is_new = true;
|
||||
$linkdate = strval(date(LinkDB::LINK_DATE_FORMAT));
|
||||
// Get title if it was provided in URL (by the bookmarklet).
|
||||
|
@ -1300,7 +1313,9 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$description = empty($_GET['description']) ? '' : escape($_GET['description']);
|
||||
$tags = empty($_GET['tags']) ? '' : escape($_GET['tags']);
|
||||
$private = !empty($_GET['private']) && $_GET['private'] === "1" ? 1 : 0;
|
||||
// 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.)
|
||||
|
||||
// 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.)
|
||||
if (empty($title) && strpos(get_url_scheme($url), 'http') !== false) {
|
||||
// Short timeout to keep the application responsive
|
||||
// The callback will fill $charset and $title with data from the downloaded page.
|
||||
|
@ -1408,7 +1423,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
header('Content-Type: text/html; charset=utf-8');
|
||||
header(
|
||||
'Content-disposition: attachment; filename=bookmarks_'
|
||||
.$selection.'_'.$now->format(LinkDB::LINK_DATE_FORMAT).'.html'
|
||||
.$selection.'_'.$now->format(LinkDB::LINK_DATE_FORMAT).'.html'
|
||||
);
|
||||
$PAGE->assign('date', $now->format(DateTime::RFC822));
|
||||
$PAGE->assign('eol', PHP_EOL);
|
||||
|
@ -1476,14 +1491,20 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager,
|
|||
$pluginMeta = $pluginManager->getPluginsMeta();
|
||||
|
||||
// Split plugins into 2 arrays: ordered enabled plugins and disabled.
|
||||
$enabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] !== false; });
|
||||
$enabledPlugins = array_filter($pluginMeta, function ($v) {
|
||||
return $v['order'] !== false;
|
||||
});
|
||||
// Load parameters.
|
||||
$enabledPlugins = load_plugin_parameter_values($enabledPlugins, $conf->get('plugins', array()));
|
||||
uasort(
|
||||
$enabledPlugins,
|
||||
function($a, $b) { return $a['order'] - $b['order']; }
|
||||
function ($a, $b) {
|
||||
return $a['order'] - $b['order'];
|
||||
}
|
||||
);
|
||||
$disabledPlugins = array_filter($pluginMeta, function($v) { return $v['order'] === false; });
|
||||
$disabledPlugins = array_filter($pluginMeta, function ($v) {
|
||||
return $v['order'] === false;
|
||||
});
|
||||
|
||||
$PAGE->assign('enabledPlugins', $enabledPlugins);
|
||||
$PAGE->assign('disabledPlugins', $disabledPlugins);
|
||||
|
@ -1500,21 +1521,23 @@ function($a, $b) { return $a['order'] - $b['order']; }
|
|||
foreach ($_POST as $param => $value) {
|
||||
$conf->set('plugins.'. $param, escape($value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$conf->set('general.enabled_plugins', save_plugin_config($_POST));
|
||||
}
|
||||
$conf->write($loginManager->isLoggedIn());
|
||||
$history->updateSettings();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while saving plugin configuration:.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
);
|
||||
|
||||
// TODO: do not handle exceptions/errors in JS.
|
||||
echo '<script>alert("'. $e->getMessage() .'");document.location=\'?do='. Router::$PAGE_PLUGINSADMIN .'\';</script>';
|
||||
echo '<script>alert("'
|
||||
. $e->getMessage()
|
||||
.'");document.location=\'?do='
|
||||
. Router::$PAGE_PLUGINSADMIN
|
||||
.'\';</script>';
|
||||
exit;
|
||||
}
|
||||
header('Location: ?do='. Router::$PAGE_PLUGINSADMIN);
|
||||
|
@ -1635,8 +1658,7 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
}
|
||||
|
||||
$linkDisp = array();
|
||||
while ($i<$end && $i<count($keys))
|
||||
{
|
||||
while ($i<$end && $i<count($keys)) {
|
||||
$link = $linksToDisplay[$keys[$i]];
|
||||
$link['description'] = format_description(
|
||||
$link['description'],
|
||||
|
@ -1739,16 +1761,19 @@ function buildLinkList($PAGE, $LINKSDB, $conf, $pluginManager, $loginManager)
|
|||
* @param SessionManager $sessionManager SessionManager instance
|
||||
* @param LoginManager $loginManager LoginManager instance
|
||||
*/
|
||||
function install($conf, $sessionManager, $loginManager) {
|
||||
function install($conf, $sessionManager, $loginManager)
|
||||
{
|
||||
// On free.fr host, make sure the /sessions directory exists, otherwise login will not work.
|
||||
if (endsWith($_SERVER['HTTP_HOST'],'.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions',0705);
|
||||
if (endsWith($_SERVER['HTTP_HOST'], '.free.fr') && !is_dir($_SERVER['DOCUMENT_ROOT'].'/sessions')) {
|
||||
mkdir($_SERVER['DOCUMENT_ROOT'].'/sessions', 0705);
|
||||
}
|
||||
|
||||
|
||||
// This part makes sure sessions works correctly.
|
||||
// (Because on some hosts, session.save_path may not be set correctly,
|
||||
// or we may not have write access to it.)
|
||||
if (isset($_GET['test_session']) && ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working'))
|
||||
{
|
||||
if (isset($_GET['test_session'])
|
||||
&& ( !isset($_SESSION) || !isset($_SESSION['session_tested']) || $_SESSION['session_tested']!='Working')) {
|
||||
// Step 2: Check if data in session is correct.
|
||||
$msg = t(
|
||||
'<pre>Sessions do not seem to work correctly on your server.<br>'.
|
||||
|
@ -1764,19 +1789,18 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
echo '<br><a href="?">'. t('Click to try again.') .'</a></pre>';
|
||||
die;
|
||||
}
|
||||
if (!isset($_SESSION['session_tested']))
|
||||
{ // Step 1 : Try to store data in session and reload page.
|
||||
if (!isset($_SESSION['session_tested'])) {
|
||||
// Step 1 : Try to store data in session and reload page.
|
||||
$_SESSION['session_tested'] = 'Working'; // Try to set a variable in session.
|
||||
header('Location: '.index_url($_SERVER).'?test_session'); // Redirect to check stored data.
|
||||
}
|
||||
if (isset($_GET['test_session']))
|
||||
{ // Step 3: Sessions are OK. Remove test parameter from URL.
|
||||
if (isset($_GET['test_session'])) {
|
||||
// Step 3: Sessions are OK. Remove test parameter from URL.
|
||||
header('Location: '.index_url($_SERVER));
|
||||
}
|
||||
|
||||
|
||||
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword']))
|
||||
{
|
||||
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) {
|
||||
$tz = 'UTC';
|
||||
if (!empty($_POST['continent']) && !empty($_POST['city'])
|
||||
&& isTimeZoneValid($_POST['continent'], $_POST['city'])
|
||||
|
@ -1807,18 +1831,20 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
try {
|
||||
// Everything is ok, let's create config file.
|
||||
$conf->write($loginManager->isLoggedIn());
|
||||
}
|
||||
catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
error_log(
|
||||
'ERROR while writing config file after installation.' . PHP_EOL .
|
||||
'ERROR while writing config file after installation.' . PHP_EOL .
|
||||
$e->getMessage()
|
||||
);
|
||||
);
|
||||
|
||||
// TODO: do not handle exceptions/errors in JS.
|
||||
echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>';
|
||||
exit;
|
||||
}
|
||||
echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>';
|
||||
echo '<script>alert('
|
||||
.'"Shaarli is now configured. '
|
||||
.'Please enter your login/password and start shaaring your links!"'
|
||||
.');document.location=\'?do=login\';</script>';
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -1842,7 +1868,7 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
|
||||
try {
|
||||
$history = new History($conf->get('resource.history'));
|
||||
} catch(Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
|
@ -1861,7 +1887,7 @@ function install($conf, $sessionManager, $loginManager) {
|
|||
$app = new \Slim\App($container);
|
||||
|
||||
// REST API routes
|
||||
$app->group('/api/v1', function() {
|
||||
$app->group('/api/v1', function () {
|
||||
$this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo');
|
||||
$this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks');
|
||||
$this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink');
|
||||
|
|
17
phpcs.xml
Normal file
17
phpcs.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="Shaarli">
|
||||
<description>The Shaarli coding standards</description>
|
||||
|
||||
<file>index.php</file>
|
||||
<file>application</file>
|
||||
<file>plugins</file>
|
||||
<file>tests</file>
|
||||
|
||||
<exclude-pattern>*/*.css</exclude-pattern>
|
||||
<exclude-pattern>*/*.js</exclude-pattern>
|
||||
|
||||
<arg name="colors"/>
|
||||
|
||||
<rule ref="PSR1"/>
|
||||
<rule ref="PSR2"/>
|
||||
</ruleset>
|
|
@ -17,7 +17,7 @@ function hook_archiveorg_render_linklist($data)
|
|||
$archive_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/archiveorg/archiveorg.html');
|
||||
|
||||
foreach ($data['links'] as &$value) {
|
||||
if($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) {
|
||||
if ($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) {
|
||||
continue;
|
||||
}
|
||||
$archive = sprintf($archive_html, $value['url'], t('View on archive.org'));
|
||||
|
|
|
@ -73,7 +73,6 @@ function hook_demo_plugin_render_header($data)
|
|||
{
|
||||
// Only execute when linklist is rendered.
|
||||
if ($data['_PAGE_'] == Router::$PAGE_LINKLIST) {
|
||||
|
||||
// If loggedin
|
||||
if ($data['_LOGGEDIN_'] === true) {
|
||||
/*
|
||||
|
@ -109,10 +108,10 @@ function hook_demo_plugin_render_header($data)
|
|||
* ],
|
||||
* ]
|
||||
* This example renders as:
|
||||
* <form form-attribute-1="form attribute 1 value" form-attribute-2="form attribute 2 value">
|
||||
* <input input-1-attribute-1="input 1 attribute 1 value" input-1-attribute-2="input 1 attribute 2 value">
|
||||
* <input input-2-attribute-1="input 2 attribute 1 value">
|
||||
* </form>
|
||||
* <form form-attribute-1="form attribute 1 value" form-attribute-2="form attribute 2 value">
|
||||
* <input input-1-attribute-1="input 1 attribute 1 value" input-1-attribute-2="input 1 attribute 2 value">
|
||||
* <input input-2-attribute-1="input 2 attribute 1 value">
|
||||
* </form>
|
||||
*/
|
||||
$form = array(
|
||||
'attr' => array(
|
||||
|
@ -448,8 +447,7 @@ function hook_demo_plugin_render_feed($data)
|
|||
foreach ($data['links'] as &$link) {
|
||||
if ($data['_PAGE_'] == Router::$PAGE_FEED_ATOM) {
|
||||
$link['description'] .= ' - ATOM Feed' ;
|
||||
}
|
||||
elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
|
||||
} elseif ($data['_PAGE_'] == Router::$PAGE_FEED_RSS) {
|
||||
$link['description'] .= ' - RSS Feed';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,6 @@ function hook_markdown_render_includes($data)
|
|||
|| $data['_PAGE_'] == Router::$PAGE_DAILY
|
||||
|| $data['_PAGE_'] == Router::$PAGE_EDITLINK
|
||||
) {
|
||||
|
||||
$data['css_files'][] = PluginManager::$PLUGINS_PATH . '/markdown/markdown.css';
|
||||
}
|
||||
|
||||
|
@ -195,8 +194,7 @@ function reverse_text2clickable($description)
|
|||
// Detect and toggle block of code
|
||||
if (!$codeBlockOn) {
|
||||
$codeBlockOn = preg_match('/^```/', $descriptionLine) > 0;
|
||||
}
|
||||
elseif (preg_match('/^```/', $descriptionLine) > 0) {
|
||||
} elseif (preg_match('/^```/', $descriptionLine) > 0) {
|
||||
$codeBlockOn = false;
|
||||
}
|
||||
|
||||
|
@ -302,13 +300,17 @@ function sanitize_html($description)
|
|||
foreach ($escapeTags as $tag) {
|
||||
$description = preg_replace_callback(
|
||||
'#<\s*'. $tag .'[^>]*>(.*</\s*'. $tag .'[^>]*>)?#is',
|
||||
function ($match) { return escape($match[0]); },
|
||||
$description);
|
||||
function ($match) {
|
||||
return escape($match[0]);
|
||||
},
|
||||
$description
|
||||
);
|
||||
}
|
||||
$description = preg_replace(
|
||||
'#(<[^>]+\s)on[a-z]*="?[^ "]*"?#is',
|
||||
'$1',
|
||||
$description);
|
||||
$description
|
||||
);
|
||||
return $description;
|
||||
}
|
||||
|
||||
|
@ -341,7 +343,7 @@ function process_markdown($description, $escape = true, $allowedProtocols = [])
|
|||
->text($processedDescription);
|
||||
$processedDescription = sanitize_html($processedDescription);
|
||||
|
||||
if(!empty($processedDescription)){
|
||||
if (!empty($processedDescription)) {
|
||||
$processedDescription = '<div class="markdown">'. $processedDescription . '</div>';
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,8 @@ function hook_pubsubhubbub_save_link($data, $conf)
|
|||
*
|
||||
* @throws Exception An error occurred.
|
||||
*/
|
||||
function nocurl_http_post($url, $postString) {
|
||||
function nocurl_http_post($url, $postString)
|
||||
{
|
||||
$params = array('http' => array(
|
||||
'method' => 'POST',
|
||||
'content' => $postString,
|
||||
|
|
|
@ -17,7 +17,8 @@ function hook_qrcode_render_linklist($data)
|
|||
$qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html');
|
||||
|
||||
foreach ($data['links'] as &$value) {
|
||||
$qrcode = sprintf($qrcode_html,
|
||||
$qrcode = sprintf(
|
||||
$qrcode_html,
|
||||
urlencode($value['url']),
|
||||
$value['url'],
|
||||
PluginManager::$PLUGINS_PATH
|
||||
|
|
|
@ -69,4 +69,3 @@ function wallabag_dummy_translation()
|
|||
t('Wallabag API URL');
|
||||
t('Wallabag API version (1 or 2)');
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class FakeApplicationUtils extends ApplicationUtils
|
|||
/**
|
||||
* Toggle HTTP requests, allow overriding the version code
|
||||
*/
|
||||
public static function getVersion($url, $timeout=0)
|
||||
public static function getVersion($url, $timeout = 0)
|
||||
{
|
||||
return self::$VERSION_CODE;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public function testGetVersionCode()
|
|||
'0.5.4',
|
||||
ApplicationUtils::getVersion(
|
||||
'https://raw.githubusercontent.com/shaarli/Shaarli/'
|
||||
.'v0.5.4/shaarli_version.php',
|
||||
.'v0.5.4/shaarli_version.php',
|
||||
$testTimeout
|
||||
)
|
||||
);
|
||||
|
@ -75,7 +75,7 @@ public function testGetVersionCode()
|
|||
self::$versionPattern,
|
||||
ApplicationUtils::getVersion(
|
||||
'https://raw.githubusercontent.com/shaarli/Shaarli/'
|
||||
.'latest/shaarli_version.php',
|
||||
.'latest/shaarli_version.php',
|
||||
$testTimeout
|
||||
)
|
||||
);
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
/**
|
||||
* Unitary tests for getIpAddressFromProxy()
|
||||
*/
|
||||
class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase {
|
||||
class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Test without proxy
|
||||
|
|
|
@ -362,7 +362,7 @@ public function testAllTags()
|
|||
public function testLinkRealUrlWithoutRedirector()
|
||||
{
|
||||
$db = new LinkDB(self::$testDatastore, false, false);
|
||||
foreach($db as $link) {
|
||||
foreach ($db as $link) {
|
||||
$this->assertEquals($link['url'], $link['real_url']);
|
||||
}
|
||||
}
|
||||
|
@ -374,13 +374,13 @@ public function testLinkRealUrlWithRedirector()
|
|||
{
|
||||
$redirector = 'http://redirector.to?';
|
||||
$db = new LinkDB(self::$testDatastore, false, false, $redirector);
|
||||
foreach($db as $link) {
|
||||
foreach ($db as $link) {
|
||||
$this->assertStringStartsWith($redirector, $link['real_url']);
|
||||
$this->assertNotFalse(strpos($link['real_url'], urlencode('://')));
|
||||
}
|
||||
|
||||
$db = new LinkDB(self::$testDatastore, false, false, $redirector, false);
|
||||
foreach($db as $link) {
|
||||
foreach ($db as $link) {
|
||||
$this->assertStringStartsWith($redirector, $link['real_url']);
|
||||
$this->assertFalse(strpos($link['real_url'], urlencode('://')));
|
||||
}
|
||||
|
|
|
@ -76,7 +76,15 @@ public function testFilter()
|
|||
|
||||
$this->assertEquals(
|
||||
self::$refDB->countUntaggedLinks(),
|
||||
count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, /*$request=*/'', /*$casesensitive=*/false, /*$visibility=*/'all', /*$untaggedonly=*/true))
|
||||
count(
|
||||
self::$linkFilter->filter(
|
||||
LinkFilter::$FILTER_TAG,
|
||||
/*$request=*/'',
|
||||
/*$casesensitive=*/false,
|
||||
/*$visibility=*/'all',
|
||||
/*$untaggedonly=*/true
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
|
|
|
@ -83,7 +83,9 @@ public function testCurlDownloadCallbackOk()
|
|||
'Date: Sat, 28 Oct 2017 12:01:33 GMT',
|
||||
'Content-Type: text/html; charset=utf-8',
|
||||
'Status: 200 OK',
|
||||
'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea',
|
||||
'end' => 'th=device-width">'
|
||||
.'<title>Refactoring · GitHub</title>'
|
||||
.'<link rel="search" type="application/opensea',
|
||||
'<title>ignored</title>',
|
||||
];
|
||||
foreach ($data as $key => $line) {
|
||||
|
@ -106,7 +108,9 @@ public function testCurlDownloadCallbackOkNoCharset()
|
|||
$callback = get_curl_download_callback($charset, $title, 'ut_curl_getinfo_no_charset');
|
||||
$data = [
|
||||
'HTTP/1.1 200 OK',
|
||||
'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea',
|
||||
'end' => 'th=device-width">'
|
||||
.'<title>Refactoring · GitHub</title>'
|
||||
.'<link rel="search" type="application/opensea',
|
||||
'<title>ignored</title>',
|
||||
];
|
||||
foreach ($data as $key => $line) {
|
||||
|
@ -126,7 +130,9 @@ public function testCurlDownloadCallbackOkHtmlCharset()
|
|||
$data = [
|
||||
'HTTP/1.1 200 OK',
|
||||
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
|
||||
'end' => 'th=device-width"><title>Refactoring · GitHub</title><link rel="search" type="application/opensea',
|
||||
'end' => 'th=device-width">'
|
||||
.'<title>Refactoring · GitHub</title>'
|
||||
.'<link rel="search" type="application/opensea',
|
||||
'<title>ignored</title>',
|
||||
];
|
||||
foreach ($data as $key => $line) {
|
||||
|
@ -211,23 +217,26 @@ public function testCountPrivateLinks()
|
|||
public function testText2clickableWithoutRedirector()
|
||||
{
|
||||
$text = 'stuff http://hello.there/is=someone#here otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here">http://hello.there/is=someone#here</a> otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here">'
|
||||
.'http://hello.there/is=someone#here</a> otherstuff';
|
||||
$processedText = text2clickable($text, '');
|
||||
$this->assertEquals($expectedText, $processedText);
|
||||
|
||||
$text = 'stuff http://hello.there/is=someone#here(please) otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">http://hello.there/is=someone#here(please)</a> otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)">'
|
||||
.'http://hello.there/is=someone#here(please)</a> otherstuff';
|
||||
$processedText = text2clickable($text, '');
|
||||
$this->assertEquals($expectedText, $processedText);
|
||||
|
||||
$text = 'stuff http://hello.there/is=someone#here(please)&no otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">http://hello.there/is=someone#here(please)&no</a> otherstuff';
|
||||
$expectedText = 'stuff <a href="http://hello.there/is=someone#here(please)&no">'
|
||||
.'http://hello.there/is=someone#here(please)&no</a> otherstuff';
|
||||
$processedText = text2clickable($text, '');
|
||||
$this->assertEquals($expectedText, $processedText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test text2clickable a redirector set.
|
||||
* Test text2clickable with a redirector set.
|
||||
*/
|
||||
public function testText2clickableWithRedirector()
|
||||
{
|
||||
|
@ -410,4 +419,3 @@ function ut_curl_getinfo_rs_ct_ko($ch, $type)
|
|||
return 'text/plain';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -218,7 +218,6 @@ public function testFindPageChangepasswdValid()
|
|||
Router::$PAGE_CHANGEPASSWORD,
|
||||
Router::findPage('do=changepasswd&stuff', array(), true)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -98,15 +98,17 @@ public function testThumbnailNotValid()
|
|||
ini_set('error_log', $oldlog);
|
||||
}
|
||||
|
||||
protected function rrmdirContent($dir) {
|
||||
protected function rrmdirContent($dir)
|
||||
{
|
||||
if (is_dir($dir)) {
|
||||
$objects = scandir($dir);
|
||||
foreach ($objects as $object) {
|
||||
if ($object != "." && $object != "..") {
|
||||
if (is_dir($dir."/".$object))
|
||||
if (is_dir($dir."/".$object)) {
|
||||
$this->rrmdirContent($dir."/".$object);
|
||||
else
|
||||
} else {
|
||||
unlink($dir."/".$object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn)
|
|||
*
|
||||
* @return bool true.
|
||||
*/
|
||||
private final function updateMethodDummy1()
|
||||
final private function updateMethodDummy1()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ private final function updateMethodDummy1()
|
|||
*
|
||||
* @return bool true.
|
||||
*/
|
||||
private final function updateMethodDummy2()
|
||||
final private function updateMethodDummy2()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ private final function updateMethodDummy2()
|
|||
*
|
||||
* @return bool true.
|
||||
*/
|
||||
private final function updateMethodDummy3()
|
||||
final private function updateMethodDummy3()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ private final function updateMethodDummy3()
|
|||
*
|
||||
* @throws Exception error.
|
||||
*/
|
||||
private final function updateMethodException()
|
||||
final private function updateMethodException()
|
||||
{
|
||||
throw new Exception('whatever');
|
||||
}
|
||||
|
|
|
@ -393,20 +393,32 @@ public function testDatastoreIds()
|
|||
$this->assertEquals('Naming conventions... #private', $linkDB[0]['description']);
|
||||
$this->assertEquals('samba cartoon web', $linkDB[0]['tags']);
|
||||
$this->assertTrue($linkDB[0]['private']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'), $linkDB[0]['created']);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'),
|
||||
$linkDB[0]['created']
|
||||
);
|
||||
|
||||
$this->assertTrue(isset($linkDB[1]));
|
||||
$this->assertFalse(isset($linkDB[1]['linkdate']));
|
||||
$this->assertEquals(1, $linkDB[1]['id']);
|
||||
$this->assertEquals('UserFriendly - Samba', $linkDB[1]['title']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'), $linkDB[1]['created']);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'),
|
||||
$linkDB[1]['created']
|
||||
);
|
||||
|
||||
$this->assertTrue(isset($linkDB[2]));
|
||||
$this->assertFalse(isset($linkDB[2]['linkdate']));
|
||||
$this->assertEquals(2, $linkDB[2]['id']);
|
||||
$this->assertEquals('Geek and Poke', $linkDB[2]['title']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'), $linkDB[2]['created']);
|
||||
$this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'), $linkDB[2]['updated']);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'),
|
||||
$linkDB[2]['created']
|
||||
);
|
||||
$this->assertEquals(
|
||||
DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'),
|
||||
$linkDB[2]['updated']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -107,4 +107,3 @@ public function testCleanupUrlQueryFragment()
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,4 +28,3 @@ public function testGetUrlScheme()
|
|||
$this->assertEquals('git', get_url_scheme('git://domain.tld/push?pull=clone#checkout'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,4 +28,3 @@ public function testUnparseFull()
|
|||
$this->assertEquals($ref, unparse_url(parse_url($ref)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
|
|||
/**
|
||||
* Helper method
|
||||
*/
|
||||
private function assertUrlIsCleaned($query='', $fragment='')
|
||||
private function assertUrlIsCleaned($query = '', $fragment = '')
|
||||
{
|
||||
$url = new Url(self::$baseUrl.$query.$fragment);
|
||||
$url->cleanup();
|
||||
|
@ -135,13 +135,13 @@ public function testCleanupMixedContent()
|
|||
'about://reader?url=' . urlencode(self::$baseUrl .'?my=stuff&is=kept')
|
||||
);
|
||||
$this->assertEquals(self::$baseUrl.'?my=stuff&is=kept', $url->cleanup());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default http scheme.
|
||||
*/
|
||||
public function testDefaultScheme() {
|
||||
public function testDefaultScheme()
|
||||
{
|
||||
$url = new Url(self::$baseUrl);
|
||||
$this->assertEquals('http', $url->getScheme());
|
||||
$url = new Url('domain.tld');
|
||||
|
|
|
@ -187,7 +187,8 @@ public function testCheckInvalidDateFormat()
|
|||
/**
|
||||
* Test generate location with valid data.
|
||||
*/
|
||||
public function testGenerateLocation() {
|
||||
public function testGenerateLocation()
|
||||
{
|
||||
$ref = 'http://localhost/?test';
|
||||
$this->assertEquals($ref, generateLocation($ref, 'localhost'));
|
||||
$ref = 'http://localhost:8080/?test';
|
||||
|
@ -199,7 +200,8 @@ public function testGenerateLocation() {
|
|||
/**
|
||||
* Test generate location - anti loop.
|
||||
*/
|
||||
public function testGenerateLocationLoop() {
|
||||
public function testGenerateLocationLoop()
|
||||
{
|
||||
$ref = 'http://localhost/?test';
|
||||
$this->assertEquals('?', generateLocation($ref, 'localhost', array('test')));
|
||||
}
|
||||
|
@ -207,7 +209,8 @@ public function testGenerateLocationLoop() {
|
|||
/**
|
||||
* Test generate location - from other domain.
|
||||
*/
|
||||
public function testGenerateLocationOut() {
|
||||
public function testGenerateLocationOut()
|
||||
{
|
||||
$ref = 'http://somewebsite.com/?test';
|
||||
$this->assertEquals('?', generateLocation($ref, 'localhost'));
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
use Shaarli\Base64Url;
|
||||
|
||||
|
||||
/**
|
||||
* Class ApiUtilsTest
|
||||
*/
|
||||
|
@ -34,7 +33,7 @@ public static function generateValidJwtToken($secret)
|
|||
$payload = Base64Url::encode('{
|
||||
"iat": '. time() .'
|
||||
}');
|
||||
$signature = Base64Url::encode(hash_hmac('sha512', $header .'.'. $payload , $secret, true));
|
||||
$signature = Base64Url::encode(hash_hmac('sha512', $header .'.'. $payload, $secret, true));
|
||||
return $header .'.'. $payload .'.'. $signature;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
use Slim\Http\Environment;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
|
@ -128,7 +127,9 @@ public function testPostLinkMinimal()
|
|||
$this->assertEquals('', $data['description']);
|
||||
$this->assertEquals([], $data['tags']);
|
||||
$this->assertEquals(false, $data['private']);
|
||||
$this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertEquals('', $data['updated']);
|
||||
|
||||
$historyEntry = $this->history->getHistory()[0];
|
||||
|
@ -171,7 +172,9 @@ public function testPostLinkFull()
|
|||
$this->assertEquals($link['description'], $data['description']);
|
||||
$this->assertEquals($link['tags'], $data['tags']);
|
||||
$this->assertEquals(true, $data['private']);
|
||||
$this->assertTrue(new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertEquals('', $data['updated']);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
use Slim\Http\Environment;
|
||||
|
@ -115,7 +114,9 @@ public function testPutLinkMinimal()
|
|||
\DateTime::createFromFormat('Ymd_His', '20150310_114651'),
|
||||
\DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
|
||||
);
|
||||
|
||||
$historyEntry = $this->history->getHistory()[0];
|
||||
$this->assertEquals(\History::UPDATED, $historyEntry['event']);
|
||||
|
@ -160,7 +161,9 @@ public function testPutLinkWithValues()
|
|||
\DateTime::createFromFormat('Ymd_His', '20150310_114651'),
|
||||
\DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
|
||||
);
|
||||
$this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
|
||||
$this->assertTrue(
|
||||
new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli\Api\Controllers;
|
||||
|
||||
|
||||
use Shaarli\Api\Exceptions\ApiBadParametersException;
|
||||
use Shaarli\Config\ConfigManager;
|
||||
use Slim\Container;
|
||||
|
|
|
@ -20,7 +20,7 @@ public function testDateFormat()
|
|||
public function testDateFormatNoTime()
|
||||
{
|
||||
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
|
||||
$this->assertRegExp('/1\. Januar 2017/', format_date($date, false,true));
|
||||
$this->assertRegExp('/1\. Januar 2017/', format_date($date, false, true));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
namespace Shaarli;
|
||||
|
||||
|
||||
use Shaarli\Config\ConfigManager;
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,7 +15,8 @@ class PluginQrcodeTest extends PHPUnit_Framework_TestCase
|
|||
/**
|
||||
* Reset plugin path
|
||||
*/
|
||||
public function setUp() {
|
||||
public function setUp()
|
||||
{
|
||||
PluginManager::$PLUGINS_PATH = 'plugins';
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
use \Shaarli\Security\SessionManager;
|
||||
use \PHPUnit\Framework\TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Test coverage for SessionManager
|
||||
*/
|
||||
|
|
|
@ -150,8 +150,8 @@ protected function addLink(
|
|||
$tags,
|
||||
$updated = '',
|
||||
$shorturl = '',
|
||||
$pinned = false)
|
||||
{
|
||||
$pinned = false
|
||||
) {
|
||||
$link = array(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
|
@ -201,7 +201,7 @@ public function reorder($order = 'DESC')
|
|||
|
||||
$order = $order === 'ASC' ? -1 : 1;
|
||||
// Reorder array by dates.
|
||||
usort($this->_links, function($a, $b) use ($order) {
|
||||
usort($this->_links, function ($a, $b) use ($order) {
|
||||
if (isset($a['sticky']) && isset($b['sticky']) && $a['sticky'] !== $b['sticky']) {
|
||||
return $a['sticky'] ? -1 : 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue