diff options
45 files changed, 3451 insertions, 390 deletions
@@ -13,7 +13,6 @@ pagecache | |||
13 | *.rtpl.php | 13 | *.rtpl.php |
14 | 14 | ||
15 | # 3rd-party dependencies | 15 | # 3rd-party dependencies |
16 | composer.lock | ||
17 | vendor/ | 16 | vendor/ |
18 | 17 | ||
19 | # Release archives | 18 | # Release archives |
@@ -6,13 +6,18 @@ _Do you want to share the links you discover?_ | |||
6 | _Shaarli is a minimalist delicious clone that you can install on your own server._ | 6 | _Shaarli is a minimalist delicious clone that you can install on your own server._ |
7 | _It is designed to be personal (single-user), fast and handy._ | 7 | _It is designed to be personal (single-user), fast and handy._ |
8 | 8 | ||
9 | [![](https://img.shields.io/travis/shaarli/Shaarli.svg?label=master)](https://travis-ci.org/shaarli/Shaarli) | 9 | [![](https://img.shields.io/badge/stable-v0.7.1-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.7.1) |
10 | [![](https://img.shields.io/travis/shaarli/Shaarli/stable.svg?label=stable)](https://travis-ci.org/shaarli/Shaarli) | 10 | [![](https://img.shields.io/travis/shaarli/Shaarli/stable.svg?label=stable)](https://travis-ci.org/shaarli/Shaarli) |
11 | [![](https://img.shields.io/github/release/shaarli/shaarli.svg)](https://github.com/shaarli/Shaarli/releases/latest/) | 11 | • |
12 | [![Docker repository](https://img.shields.io/docker/pulls/shaarli/shaarli.svg)](https://hub.docker.com/r/shaarli/shaarli/) | 12 | [![](https://img.shields.io/badge/latest-v0.8.4-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.8.4) |
13 | [![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli) | ||
14 | • | ||
15 | [![](https://img.shields.io/badge/master-v0.9.x-blue.svg)](https://github.com/shaarli/Shaarli) | ||
16 | [![](https://img.shields.io/travis/shaarli/Shaarli.svg?label=master)](https://travis-ci.org/shaarli/Shaarli) | ||
13 | 17 | ||
14 | [![Join the chat at https://gitter.im/shaarli/Shaarli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shaarli/Shaarli) | 18 | [![Join the chat at https://gitter.im/shaarli/Shaarli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shaarli/Shaarli) |
15 | [![Bountysource](https://www.bountysource.com/badge/team?team_id=19583&style=bounties_received)](https://www.bountysource.com/teams/shaarli/issues) | 19 | [![Bountysource](https://www.bountysource.com/badge/team?team_id=19583&style=bounties_received)](https://www.bountysource.com/teams/shaarli/issues) |
20 | [![Docker repository](https://img.shields.io/docker/pulls/shaarli/shaarli.svg)](https://hub.docker.com/r/shaarli/shaarli/) | ||
16 | 21 | ||
17 | ## Quickstart | 22 | ## Quickstart |
18 | - [Wiki/documentation](https://github.com/shaarli/Shaarli/wiki) | 23 | - [Wiki/documentation](https://github.com/shaarli/Shaarli/wiki) |
diff --git a/application/ApplicationUtils.php b/application/ApplicationUtils.php index a0f482b0..85dcbeeb 100644 --- a/application/ApplicationUtils.php +++ b/application/ApplicationUtils.php | |||
@@ -4,9 +4,13 @@ | |||
4 | */ | 4 | */ |
5 | class ApplicationUtils | 5 | class ApplicationUtils |
6 | { | 6 | { |
7 | /** | ||
8 | * @var string File containing the current version | ||
9 | */ | ||
10 | public static $VERSION_FILE = 'shaarli_version.php'; | ||
11 | |||
7 | private static $GIT_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli'; | 12 | private static $GIT_URL = 'https://raw.githubusercontent.com/shaarli/Shaarli'; |
8 | private static $GIT_BRANCHES = array('master', 'stable'); | 13 | private static $GIT_BRANCHES = array('latest', 'stable'); |
9 | private static $VERSION_FILE = 'shaarli_version.php'; | ||
10 | private static $VERSION_START_TAG = '<?php /* '; | 14 | private static $VERSION_START_TAG = '<?php /* '; |
11 | private static $VERSION_END_TAG = ' */ ?>'; | 15 | private static $VERSION_END_TAG = ' */ ?>'; |
12 | 16 | ||
@@ -29,6 +33,30 @@ class ApplicationUtils | |||
29 | return false; | 33 | return false; |
30 | } | 34 | } |
31 | 35 | ||
36 | return $data; | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Retrieve the version from a remote URL or a file. | ||
41 | * | ||
42 | * @param string $remote URL or file to fetch. | ||
43 | * @param int $timeout For URLs fetching. | ||
44 | * | ||
45 | * @return bool|string The version or false if it couldn't be retrieved. | ||
46 | */ | ||
47 | public static function getVersion($remote, $timeout = 2) | ||
48 | { | ||
49 | if (startsWith($remote, 'http')) { | ||
50 | if (($data = static::getLatestGitVersionCode($remote, $timeout)) === false) { | ||
51 | return false; | ||
52 | } | ||
53 | } else { | ||
54 | if (! is_file($remote)) { | ||
55 | return false; | ||
56 | } | ||
57 | $data = file_get_contents($remote); | ||
58 | } | ||
59 | |||
32 | return str_replace( | 60 | return str_replace( |
33 | array(self::$VERSION_START_TAG, self::$VERSION_END_TAG, PHP_EOL), | 61 | array(self::$VERSION_START_TAG, self::$VERSION_END_TAG, PHP_EOL), |
34 | array('', '', ''), | 62 | array('', '', ''), |
@@ -65,13 +93,10 @@ class ApplicationUtils | |||
65 | $isLoggedIn, | 93 | $isLoggedIn, |
66 | $branch='stable') | 94 | $branch='stable') |
67 | { | 95 | { |
68 | if (! $isLoggedIn) { | 96 | // Do not check versions for visitors |
69 | // Do not check versions for visitors | 97 | // Do not check if the user doesn't want to |
70 | return false; | 98 | // Do not check with dev version |
71 | } | 99 | if (! $isLoggedIn || empty($enableCheck) || $currentVersion === 'dev') { |
72 | |||
73 | if (empty($enableCheck)) { | ||
74 | // Do not check if the user doesn't want to | ||
75 | return false; | 100 | return false; |
76 | } | 101 | } |
77 | 102 | ||
@@ -93,7 +118,7 @@ class ApplicationUtils | |||
93 | 118 | ||
94 | // Late Static Binding allows overriding within tests | 119 | // Late Static Binding allows overriding within tests |
95 | // See http://php.net/manual/en/language.oop5.late-static-bindings.php | 120 | // See http://php.net/manual/en/language.oop5.late-static-bindings.php |
96 | $latestVersion = static::getLatestGitVersionCode( | 121 | $latestVersion = static::getVersion( |
97 | self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE | 122 | self::$GIT_URL . '/' . $branch . '/' . self::$VERSION_FILE |
98 | ); | 123 | ); |
99 | 124 | ||
diff --git a/application/LinkDB.php b/application/LinkDB.php index 2fb15040..0d3c85bd 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php | |||
@@ -138,10 +138,10 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
138 | if (!isset($value['id']) || empty($value['url'])) { | 138 | if (!isset($value['id']) || empty($value['url'])) { |
139 | die('Internal Error: A link should always have an id and URL.'); | 139 | die('Internal Error: A link should always have an id and URL.'); |
140 | } | 140 | } |
141 | if ((! empty($offset) && ! is_int($offset)) || ! is_int($value['id'])) { | 141 | if (($offset !== null && ! is_int($offset)) || ! is_int($value['id'])) { |
142 | die('You must specify an integer as a key.'); | 142 | die('You must specify an integer as a key.'); |
143 | } | 143 | } |
144 | if (! empty($offset) && $offset !== $value['id']) { | 144 | if ($offset !== null && $offset !== $value['id']) { |
145 | die('Array offset and link ID must be equal.'); | 145 | die('Array offset and link ID must be equal.'); |
146 | } | 146 | } |
147 | 147 | ||
diff --git a/application/PageBuilder.php b/application/PageBuilder.php index b133dee8..8e39455b 100644 --- a/application/PageBuilder.php +++ b/application/PageBuilder.php | |||
@@ -1,5 +1,7 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | use Shaarli\Config\ConfigManager; | ||
4 | |||
3 | /** | 5 | /** |
4 | * This class is in charge of building the final page. | 6 | * This class is in charge of building the final page. |
5 | * (This is basically a wrapper around RainTPL which pre-fills some fields.) | 7 | * (This is basically a wrapper around RainTPL which pre-fills some fields.) |
diff --git a/application/TimeZone.php b/application/TimeZone.php index 36a8fb12..c1869ef8 100644 --- a/application/TimeZone.php +++ b/application/TimeZone.php | |||
@@ -1,23 +1,42 @@ | |||
1 | <?php | 1 | <?php |
2 | /** | 2 | /** |
3 | * Generates the timezone selection form and JavaScript. | 3 | * Generates a list of available timezone continents and cities. |
4 | * | 4 | * |
5 | * Note: 'UTC/UTC' is mapped to 'UTC' to form a valid option | 5 | * Two distinct array based on available timezones |
6 | * and the one selected in the settings: | ||
7 | * - (0) continents: | ||
8 | * + list of available continents | ||
9 | * + special key 'selected' containing the value of the selected timezone's continent | ||
10 | * - (1) cities: | ||
11 | * + list of available cities associated with their continent | ||
12 | * + special key 'selected' containing the value of the selected timezone's city (without the continent) | ||
6 | * | 13 | * |
7 | * Example: preselect Europe/Paris | 14 | * Example: |
8 | * list($htmlform, $js) = generateTimeZoneForm('Europe/Paris'); | 15 | * [ |
16 | * [ | ||
17 | * 'America', | ||
18 | * 'Europe', | ||
19 | * 'selected' => 'Europe', | ||
20 | * ], | ||
21 | * [ | ||
22 | * ['continent' => 'America', 'city' => 'Toronto'], | ||
23 | * ['continent' => 'Europe', 'city' => 'Paris'], | ||
24 | * 'selected' => 'Paris', | ||
25 | * ], | ||
26 | * ]; | ||
9 | * | 27 | * |
28 | * Notes: | ||
29 | * - 'UTC/UTC' is mapped to 'UTC' to form a valid option | ||
30 | * - a few timezone cities includes the country/state, such as Argentina/Buenos_Aires | ||
31 | * - these arrays are designed to build timezone selects in template files with any HTML structure | ||
32 | * | ||
33 | * @param array $installedTimeZones List of installed timezones as string | ||
10 | * @param string $preselectedTimezone preselected timezone (optional) | 34 | * @param string $preselectedTimezone preselected timezone (optional) |
11 | * | 35 | * |
12 | * @return array containing the generated HTML form and Javascript code | 36 | * @return array[] continents and cities |
13 | **/ | 37 | **/ |
14 | function generateTimeZoneForm($preselectedTimezone='') | 38 | function generateTimeZoneData($installedTimeZones, $preselectedTimezone = '') |
15 | { | 39 | { |
16 | // Select the server timezone | ||
17 | if ($preselectedTimezone == '') { | ||
18 | $preselectedTimezone = date_default_timezone_get(); | ||
19 | } | ||
20 | |||
21 | if ($preselectedTimezone == 'UTC') { | 40 | if ($preselectedTimezone == 'UTC') { |
22 | $pcity = $pcontinent = 'UTC'; | 41 | $pcity = $pcontinent = 'UTC'; |
23 | } else { | 42 | } else { |
@@ -27,62 +46,30 @@ function generateTimeZoneForm($preselectedTimezone='') | |||
27 | $pcity = substr($preselectedTimezone, $spos+1); | 46 | $pcity = substr($preselectedTimezone, $spos+1); |
28 | } | 47 | } |
29 | 48 | ||
30 | // The list is in the form 'Europe/Paris', 'America/Argentina/Buenos_Aires' | 49 | $continents = []; |
31 | // We split the list in continents/cities. | 50 | $cities = []; |
32 | $continents = array(); | 51 | foreach ($installedTimeZones as $tz) { |
33 | $cities = array(); | ||
34 | |||
35 | // TODO: use a template to generate the HTML/Javascript form | ||
36 | |||
37 | foreach (timezone_identifiers_list() as $tz) { | ||
38 | if ($tz == 'UTC') { | 52 | if ($tz == 'UTC') { |
39 | $tz = 'UTC/UTC'; | 53 | $tz = 'UTC/UTC'; |
40 | } | 54 | } |
41 | $spos = strpos($tz, '/'); | 55 | $spos = strpos($tz, '/'); |
42 | 56 | ||
43 | if ($spos !== false) { | 57 | // Ignore invalid timezones |
44 | $continent = substr($tz, 0, $spos); | 58 | if ($spos === false) { |
45 | $city = substr($tz, $spos+1); | 59 | continue; |
46 | $continents[$continent] = 1; | ||
47 | |||
48 | if (!isset($cities[$continent])) { | ||
49 | $cities[$continent] = ''; | ||
50 | } | ||
51 | $cities[$continent] .= '<option value="'.$city.'"'; | ||
52 | if ($pcity == $city) { | ||
53 | $cities[$continent] .= ' selected="selected"'; | ||
54 | } | ||
55 | $cities[$continent] .= '>'.$city.'</option>'; | ||
56 | } | 60 | } |
57 | } | ||
58 | |||
59 | $continentsHtml = ''; | ||
60 | $continents = array_keys($continents); | ||
61 | 61 | ||
62 | foreach ($continents as $continent) { | 62 | $continent = substr($tz, 0, $spos); |
63 | $continentsHtml .= '<option value="'.$continent.'"'; | 63 | $city = substr($tz, $spos+1); |
64 | if ($pcontinent == $continent) { | 64 | $cities[] = ['continent' => $continent, 'city' => $city]; |
65 | $continentsHtml .= ' selected="selected"'; | 65 | $continents[$continent] = true; |
66 | } | ||
67 | $continentsHtml .= '>'.$continent.'</option>'; | ||
68 | } | 66 | } |
69 | 67 | ||
70 | // Timezone selection form | 68 | $continents = array_keys($continents); |
71 | $timezoneForm = 'Continent:'; | 69 | $continents['selected'] = $pcontinent; |
72 | $timezoneForm .= '<select name="continent" id="continent" onChange="onChangecontinent();">'; | 70 | $cities['selected'] = $pcity; |
73 | $timezoneForm .= $continentsHtml.'</select>'; | ||
74 | $timezoneForm .= ' City:'; | ||
75 | $timezoneForm .= '<select name="city" id="city">'.$cities[$pcontinent].'</select><br />'; | ||
76 | |||
77 | // Javascript handler - updates the city list when the user selects a continent | ||
78 | $timezoneJs = '<script>'; | ||
79 | $timezoneJs .= 'function onChangecontinent() {'; | ||
80 | $timezoneJs .= 'document.getElementById("city").innerHTML ='; | ||
81 | $timezoneJs .= ' citiescontinent[document.getElementById("continent").value]; }'; | ||
82 | $timezoneJs .= 'var citiescontinent = '.json_encode($cities).';'; | ||
83 | $timezoneJs .= '</script>'; | ||
84 | 71 | ||
85 | return array($timezoneForm, $timezoneJs); | 72 | return [$continents, $cities]; |
86 | } | 73 | } |
87 | 74 | ||
88 | /** | 75 | /** |
diff --git a/application/Updater.php b/application/Updater.php index efbfc832..0fb68c5a 100644 --- a/application/Updater.php +++ b/application/Updater.php | |||
@@ -396,6 +396,50 @@ class Updater | |||
396 | 396 | ||
397 | return true; | 397 | return true; |
398 | } | 398 | } |
399 | |||
400 | /** | ||
401 | * Update updates.check_updates_branch setting. | ||
402 | * | ||
403 | * If the current major version digit matches the latest branch | ||
404 | * major version digit, we set the branch to `latest`, | ||
405 | * otherwise we'll check updates on the `stable` branch. | ||
406 | * | ||
407 | * No update required for the dev version. | ||
408 | * | ||
409 | * Note: due to hardcoded URL and lack of dependency injection, this is not unit testable. | ||
410 | * | ||
411 | * FIXME! This needs to be removed when we switch to first digit major version | ||
412 | * instead of the second one since the versionning process will change. | ||
413 | */ | ||
414 | public function updateMethodCheckUpdateRemoteBranch() | ||
415 | { | ||
416 | if (shaarli_version === 'dev' || $this->conf->get('updates.check_updates_branch') === 'latest') { | ||
417 | return true; | ||
418 | } | ||
419 | |||
420 | // Get latest branch major version digit | ||
421 | $latestVersion = ApplicationUtils::getLatestGitVersionCode( | ||
422 | 'https://raw.githubusercontent.com/shaarli/Shaarli/latest/shaarli_version.php', | ||
423 | 5 | ||
424 | ); | ||
425 | if (preg_match('/(\d+)\.\d+$/', $latestVersion, $matches) === false) { | ||
426 | return false; | ||
427 | } | ||
428 | $latestMajor = $matches[1]; | ||
429 | |||
430 | // Get current major version digit | ||
431 | preg_match('/(\d+)\.\d+$/', shaarli_version, $matches); | ||
432 | $currentMajor = $matches[1]; | ||
433 | |||
434 | if ($currentMajor === $latestMajor) { | ||
435 | $branch = 'latest'; | ||
436 | } else { | ||
437 | $branch = 'stable'; | ||
438 | } | ||
439 | $this->conf->set('updates.check_updates_branch', $branch); | ||
440 | $this->conf->write($this->isLoggedIn); | ||
441 | return true; | ||
442 | } | ||
399 | } | 443 | } |
400 | 444 | ||
401 | /** | 445 | /** |
diff --git a/application/Utils.php b/application/Utils.php index 5c077450..ab463af9 100644 --- a/application/Utils.php +++ b/application/Utils.php | |||
@@ -321,25 +321,117 @@ function normalize_spaces($string) | |||
321 | * otherwise default format '%c' will be returned. | 321 | * otherwise default format '%c' will be returned. |
322 | * | 322 | * |
323 | * @param DateTime $date to format. | 323 | * @param DateTime $date to format. |
324 | * @param bool $time Displays time if true. | ||
324 | * @param bool $intl Use international format if true. | 325 | * @param bool $intl Use international format if true. |
325 | * | 326 | * |
326 | * @return bool|string Formatted date, or false if the input is invalid. | 327 | * @return bool|string Formatted date, or false if the input is invalid. |
327 | */ | 328 | */ |
328 | function format_date($date, $intl = true) | 329 | function format_date($date, $time = true, $intl = true) |
329 | { | 330 | { |
330 | if (! $date instanceof DateTime) { | 331 | if (! $date instanceof DateTime) { |
331 | return false; | 332 | return false; |
332 | } | 333 | } |
333 | 334 | ||
334 | if (! $intl || ! class_exists('IntlDateFormatter')) { | 335 | if (! $intl || ! class_exists('IntlDateFormatter')) { |
335 | return strftime('%c', $date->getTimestamp()); | 336 | $format = $time ? '%c' : '%x'; |
337 | return strftime($format, $date->getTimestamp()); | ||
336 | } | 338 | } |
337 | 339 | ||
338 | $formatter = new IntlDateFormatter( | 340 | $formatter = new IntlDateFormatter( |
339 | setlocale(LC_TIME, 0), | 341 | setlocale(LC_TIME, 0), |
340 | IntlDateFormatter::LONG, | 342 | IntlDateFormatter::LONG, |
341 | IntlDateFormatter::LONG | 343 | $time ? IntlDateFormatter::LONG : IntlDateFormatter::NONE |
342 | ); | 344 | ); |
343 | 345 | ||
344 | return $formatter->format($date); | 346 | return $formatter->format($date); |
345 | } | 347 | } |
348 | |||
349 | /** | ||
350 | * Check if the input is an integer, no matter its real type. | ||
351 | * | ||
352 | * PHP is a bit messy regarding this: | ||
353 | * - is_int returns false if the input is a string | ||
354 | * - ctype_digit returns false if the input is an integer or negative | ||
355 | * | ||
356 | * @param mixed $input value | ||
357 | * | ||
358 | * @return bool true if the input is an integer, false otherwise | ||
359 | */ | ||
360 | function is_integer_mixed($input) | ||
361 | { | ||
362 | if (is_array($input) || is_bool($input) || is_object($input)) { | ||
363 | return false; | ||
364 | } | ||
365 | $input = strval($input); | ||
366 | return ctype_digit($input) || (startsWith($input, '-') && ctype_digit(substr($input, 1))); | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * Convert post_max_size/upload_max_filesize (e.g. '16M') parameters to bytes. | ||
371 | * | ||
372 | * @param string $val Size expressed in string. | ||
373 | * | ||
374 | * @return int Size expressed in bytes. | ||
375 | */ | ||
376 | function return_bytes($val) | ||
377 | { | ||
378 | if (is_integer_mixed($val) || $val === '0' || empty($val)) { | ||
379 | return $val; | ||
380 | } | ||
381 | $val = trim($val); | ||
382 | $last = strtolower($val[strlen($val)-1]); | ||
383 | $val = intval(substr($val, 0, -1)); | ||
384 | switch($last) { | ||
385 | case 'g': $val *= 1024; | ||
386 | case 'm': $val *= 1024; | ||
387 | case 'k': $val *= 1024; | ||
388 | } | ||
389 | return $val; | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * Return a human readable size from bytes. | ||
394 | * | ||
395 | * @param int $bytes value | ||
396 | * | ||
397 | * @return string Human readable size | ||
398 | */ | ||
399 | function human_bytes($bytes) | ||
400 | { | ||
401 | if ($bytes === '') { | ||
402 | return t('Setting not set'); | ||
403 | } | ||
404 | if (! is_integer_mixed($bytes)) { | ||
405 | return $bytes; | ||
406 | } | ||
407 | $bytes = intval($bytes); | ||
408 | if ($bytes === 0) { | ||
409 | return t('Unlimited'); | ||
410 | } | ||
411 | |||
412 | $units = [t('B'), t('kiB'), t('MiB'), t('GiB')]; | ||
413 | for ($i = 0; $i < count($units) && $bytes >= 1024; ++$i) { | ||
414 | $bytes /= 1024; | ||
415 | } | ||
416 | |||
417 | return round($bytes) . $units[$i]; | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * Try to determine max file size for uploads (POST). | ||
422 | * Returns an integer (in bytes) or formatted depending on $format. | ||
423 | * | ||
424 | * @param mixed $limitPost post_max_size PHP setting | ||
425 | * @param mixed $limitUpload upload_max_filesize PHP setting | ||
426 | * @param bool $format Format max upload size to human readable size | ||
427 | * | ||
428 | * @return int|string max upload file size | ||
429 | */ | ||
430 | function get_max_upload_size($limitPost, $limitUpload, $format = true) | ||
431 | { | ||
432 | $size1 = return_bytes($limitPost); | ||
433 | $size2 = return_bytes($limitUpload); | ||
434 | // Return the smaller of two: | ||
435 | $maxsize = min($size1, $size2); | ||
436 | return $format ? human_bytes($maxsize) : $maxsize; | ||
437 | } | ||
diff --git a/application/api/ApiUtils.php b/application/api/ApiUtils.php index d4015865..b8155a34 100644 --- a/application/api/ApiUtils.php +++ b/application/api/ApiUtils.php | |||
@@ -12,7 +12,7 @@ class ApiUtils | |||
12 | /** | 12 | /** |
13 | * Validates a JWT token authenticity. | 13 | * Validates a JWT token authenticity. |
14 | * | 14 | * |
15 | * @param string $token JWT token extracted from the headers. | 15 | * @param string $token JWT token extracted from the headers. |
16 | * @param string $secret API secret set in the settings. | 16 | * @param string $secret API secret set in the settings. |
17 | * | 17 | * |
18 | * @throws ApiAuthorizationException the token is not valid. | 18 | * @throws ApiAuthorizationException the token is not valid. |
@@ -50,7 +50,7 @@ class ApiUtils | |||
50 | /** | 50 | /** |
51 | * Format a Link for the REST API. | 51 | * Format a Link for the REST API. |
52 | * | 52 | * |
53 | * @param array $link Link data read from the datastore. | 53 | * @param array $link Link data read from the datastore. |
54 | * @param string $indexUrl Shaarli's index URL (used for relative URL). | 54 | * @param string $indexUrl Shaarli's index URL (used for relative URL). |
55 | * | 55 | * |
56 | * @return array Link data formatted for the REST API. | 56 | * @return array Link data formatted for the REST API. |
@@ -77,4 +77,35 @@ class ApiUtils | |||
77 | } | 77 | } |
78 | return $out; | 78 | return $out; |
79 | } | 79 | } |
80 | |||
81 | /** | ||
82 | * Convert a link given through a request, to a valid link for LinkDB. | ||
83 | * | ||
84 | * If no URL is provided, it will generate a local note URL. | ||
85 | * If no title is provided, it will use the URL as title. | ||
86 | * | ||
87 | * @param array $input Request Link. | ||
88 | * @param bool $defaultPrivate Request Link. | ||
89 | * | ||
90 | * @return array Formatted link. | ||
91 | */ | ||
92 | public static function buildLinkFromRequest($input, $defaultPrivate) | ||
93 | { | ||
94 | $input['url'] = ! empty($input['url']) ? cleanup_url($input['url']) : ''; | ||
95 | if (isset($input['private'])) { | ||
96 | $private = filter_var($input['private'], FILTER_VALIDATE_BOOLEAN); | ||
97 | } else { | ||
98 | $private = $defaultPrivate; | ||
99 | } | ||
100 | |||
101 | $link = [ | ||
102 | 'title' => ! empty($input['title']) ? $input['title'] : $input['url'], | ||
103 | 'url' => $input['url'], | ||
104 | 'description' => ! empty($input['description']) ? $input['description'] : '', | ||
105 | 'tags' => ! empty($input['tags']) ? implode(' ', $input['tags']) : '', | ||
106 | 'private' => $private, | ||
107 | 'created' => new \DateTime(), | ||
108 | ]; | ||
109 | return $link; | ||
110 | } | ||
80 | } | 111 | } |
diff --git a/application/api/controllers/ApiController.php b/application/api/controllers/ApiController.php index 1dd47f17..f35b923a 100644 --- a/application/api/controllers/ApiController.php +++ b/application/api/controllers/ApiController.php | |||
@@ -51,4 +51,14 @@ abstract class ApiController | |||
51 | $this->jsonStyle = null; | 51 | $this->jsonStyle = null; |
52 | } | 52 | } |
53 | } | 53 | } |
54 | |||
55 | /** | ||
56 | * Get the container. | ||
57 | * | ||
58 | * @return Container | ||
59 | */ | ||
60 | public function getCi() | ||
61 | { | ||
62 | return $this->ci; | ||
63 | } | ||
54 | } | 64 | } |
diff --git a/application/api/controllers/Links.php b/application/api/controllers/Links.php index d4f1a09c..0db10fd0 100644 --- a/application/api/controllers/Links.php +++ b/application/api/controllers/Links.php | |||
@@ -97,11 +97,53 @@ class Links extends ApiController | |||
97 | */ | 97 | */ |
98 | public function getLink($request, $response, $args) | 98 | public function getLink($request, $response, $args) |
99 | { | 99 | { |
100 | if (! isset($this->linkDb[$args['id']])) { | 100 | if (!isset($this->linkDb[$args['id']])) { |
101 | throw new ApiLinkNotFoundException(); | 101 | throw new ApiLinkNotFoundException(); |
102 | } | 102 | } |
103 | $index = index_url($this->ci['environment']); | 103 | $index = index_url($this->ci['environment']); |
104 | $out = ApiUtils::formatLink($this->linkDb[$args['id']], $index); | 104 | $out = ApiUtils::formatLink($this->linkDb[$args['id']], $index); |
105 | |||
105 | return $response->withJson($out, 200, $this->jsonStyle); | 106 | return $response->withJson($out, 200, $this->jsonStyle); |
106 | } | 107 | } |
108 | |||
109 | /** | ||
110 | * Creates a new link from posted request body. | ||
111 | * | ||
112 | * @param Request $request Slim request. | ||
113 | * @param Response $response Slim response. | ||
114 | * | ||
115 | * @return Response response. | ||
116 | */ | ||
117 | public function postLink($request, $response) | ||
118 | { | ||
119 | $data = $request->getParsedBody(); | ||
120 | $link = ApiUtils::buildLinkFromRequest($data, $this->conf->get('privacy.default_private_links')); | ||
121 | // duplicate by URL, return 409 Conflict | ||
122 | if (! empty($link['url']) && ! empty($dup = $this->linkDb->getLinkFromUrl($link['url']))) { | ||
123 | return $response->withJson( | ||
124 | ApiUtils::formatLink($dup, index_url($this->ci['environment'])), | ||
125 | 409, | ||
126 | $this->jsonStyle | ||
127 | ); | ||
128 | } | ||
129 | |||
130 | $link['id'] = $this->linkDb->getNextId(); | ||
131 | $link['shorturl'] = link_small_hash($link['created'], $link['id']); | ||
132 | |||
133 | // note: general relative URL | ||
134 | if (empty($link['url'])) { | ||
135 | $link['url'] = '?' . $link['shorturl']; | ||
136 | } | ||
137 | |||
138 | if (empty($link['title'])) { | ||
139 | $link['title'] = $link['url']; | ||
140 | } | ||
141 | |||
142 | $this->linkDb[$link['id']] = $link; | ||
143 | $this->linkDb->save($this->conf->get('resource.page_cache')); | ||
144 | $out = ApiUtils::formatLink($link, index_url($this->ci['environment'])); | ||
145 | $redirect = $this->ci->router->relativePathFor('getLink', ['id' => $link['id']]); | ||
146 | return $response->withAddedHeader('Location', $redirect) | ||
147 | ->withJson($out, 201, $this->jsonStyle); | ||
148 | } | ||
107 | } | 149 | } |
diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..b285fcc9 --- /dev/null +++ b/composer.lock | |||
@@ -0,0 +1,2424 @@ | |||
1 | { | ||
2 | "_readme": [ | ||
3 | "This file locks the dependencies of your project to a known state", | ||
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", | ||
5 | "This file is @generated automatically" | ||
6 | ], | ||
7 | "content-hash": "ffcfc8e42f14183de6ef90874429e77a", | ||
8 | "packages": [ | ||
9 | { | ||
10 | "name": "container-interop/container-interop", | ||
11 | "version": "1.2.0", | ||
12 | "source": { | ||
13 | "type": "git", | ||
14 | "url": "https://github.com/container-interop/container-interop.git", | ||
15 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" | ||
16 | }, | ||
17 | "dist": { | ||
18 | "type": "zip", | ||
19 | "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", | ||
20 | "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", | ||
21 | "shasum": "" | ||
22 | }, | ||
23 | "require": { | ||
24 | "psr/container": "^1.0" | ||
25 | }, | ||
26 | "type": "library", | ||
27 | "autoload": { | ||
28 | "psr-4": { | ||
29 | "Interop\\Container\\": "src/Interop/Container/" | ||
30 | } | ||
31 | }, | ||
32 | "notification-url": "https://packagist.org/downloads/", | ||
33 | "license": [ | ||
34 | "MIT" | ||
35 | ], | ||
36 | "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", | ||
37 | "homepage": "https://github.com/container-interop/container-interop", | ||
38 | "time": "2017-02-14T19:40:03+00:00" | ||
39 | }, | ||
40 | { | ||
41 | "name": "erusev/parsedown", | ||
42 | "version": "1.6.0", | ||
43 | "source": { | ||
44 | "type": "git", | ||
45 | "url": "https://github.com/erusev/parsedown.git", | ||
46 | "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" | ||
47 | }, | ||
48 | "dist": { | ||
49 | "type": "zip", | ||
50 | "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", | ||
51 | "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", | ||
52 | "shasum": "" | ||
53 | }, | ||
54 | "type": "library", | ||
55 | "autoload": { | ||
56 | "psr-0": { | ||
57 | "Parsedown": "" | ||
58 | } | ||
59 | }, | ||
60 | "notification-url": "https://packagist.org/downloads/", | ||
61 | "license": [ | ||
62 | "MIT" | ||
63 | ], | ||
64 | "authors": [ | ||
65 | { | ||
66 | "name": "Emanuil Rusev", | ||
67 | "email": "hello@erusev.com", | ||
68 | "homepage": "http://erusev.com" | ||
69 | } | ||
70 | ], | ||
71 | "description": "Parser for Markdown.", | ||
72 | "homepage": "http://parsedown.org", | ||
73 | "keywords": [ | ||
74 | "markdown", | ||
75 | "parser" | ||
76 | ], | ||
77 | "time": "2015-10-04T16:44:32+00:00" | ||
78 | }, | ||
79 | { | ||
80 | "name": "katzgrau/klogger", | ||
81 | "version": "1.2.1", | ||
82 | "source": { | ||
83 | "type": "git", | ||
84 | "url": "https://github.com/katzgrau/KLogger.git", | ||
85 | "reference": "a4ed373fa8a214aa4ae7aa4f221fe2c6ce862ef1" | ||
86 | }, | ||
87 | "dist": { | ||
88 | "type": "zip", | ||
89 | "url": "https://api.github.com/repos/katzgrau/KLogger/zipball/a4ed373fa8a214aa4ae7aa4f221fe2c6ce862ef1", | ||
90 | "reference": "a4ed373fa8a214aa4ae7aa4f221fe2c6ce862ef1", | ||
91 | "shasum": "" | ||
92 | }, | ||
93 | "require": { | ||
94 | "php": ">=5.3", | ||
95 | "psr/log": "^1.0.0" | ||
96 | }, | ||
97 | "require-dev": { | ||
98 | "phpunit/phpunit": "4.0.*" | ||
99 | }, | ||
100 | "type": "library", | ||
101 | "autoload": { | ||
102 | "psr-4": { | ||
103 | "Katzgrau\\KLogger\\": "src/" | ||
104 | }, | ||
105 | "classmap": [ | ||
106 | "src/" | ||
107 | ] | ||
108 | }, | ||
109 | "notification-url": "https://packagist.org/downloads/", | ||
110 | "license": [ | ||
111 | "MIT" | ||
112 | ], | ||
113 | "authors": [ | ||
114 | { | ||
115 | "name": "Kenny Katzgrau", | ||
116 | "email": "katzgrau@gmail.com" | ||
117 | }, | ||
118 | { | ||
119 | "name": "Dan Horrigan", | ||
120 | "email": "dan@dhorrigan.com" | ||
121 | } | ||
122 | ], | ||
123 | "description": "A Simple Logging Class", | ||
124 | "keywords": [ | ||
125 | "logging" | ||
126 | ], | ||
127 | "time": "2016-11-07T19:29:14+00:00" | ||
128 | }, | ||
129 | { | ||
130 | "name": "nikic/fast-route", | ||
131 | "version": "v1.2.0", | ||
132 | "source": { | ||
133 | "type": "git", | ||
134 | "url": "https://github.com/nikic/FastRoute.git", | ||
135 | "reference": "b5f95749071c82a8e0f58586987627054400cdf6" | ||
136 | }, | ||
137 | "dist": { | ||
138 | "type": "zip", | ||
139 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6", | ||
140 | "reference": "b5f95749071c82a8e0f58586987627054400cdf6", | ||
141 | "shasum": "" | ||
142 | }, | ||
143 | "require": { | ||
144 | "php": ">=5.4.0" | ||
145 | }, | ||
146 | "type": "library", | ||
147 | "autoload": { | ||
148 | "psr-4": { | ||
149 | "FastRoute\\": "src/" | ||
150 | }, | ||
151 | "files": [ | ||
152 | "src/functions.php" | ||
153 | ] | ||
154 | }, | ||
155 | "notification-url": "https://packagist.org/downloads/", | ||
156 | "license": [ | ||
157 | "BSD-3-Clause" | ||
158 | ], | ||
159 | "authors": [ | ||
160 | { | ||
161 | "name": "Nikita Popov", | ||
162 | "email": "nikic@php.net" | ||
163 | } | ||
164 | ], | ||
165 | "description": "Fast request router for PHP", | ||
166 | "keywords": [ | ||
167 | "router", | ||
168 | "routing" | ||
169 | ], | ||
170 | "time": "2017-01-19T11:35:12+00:00" | ||
171 | }, | ||
172 | { | ||
173 | "name": "pimple/pimple", | ||
174 | "version": "v3.0.2", | ||
175 | "source": { | ||
176 | "type": "git", | ||
177 | "url": "https://github.com/silexphp/Pimple.git", | ||
178 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a" | ||
179 | }, | ||
180 | "dist": { | ||
181 | "type": "zip", | ||
182 | "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a", | ||
183 | "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a", | ||
184 | "shasum": "" | ||
185 | }, | ||
186 | "require": { | ||
187 | "php": ">=5.3.0" | ||
188 | }, | ||
189 | "type": "library", | ||
190 | "extra": { | ||
191 | "branch-alias": { | ||
192 | "dev-master": "3.0.x-dev" | ||
193 | } | ||
194 | }, | ||
195 | "autoload": { | ||
196 | "psr-0": { | ||
197 | "Pimple": "src/" | ||
198 | } | ||
199 | }, | ||
200 | "notification-url": "https://packagist.org/downloads/", | ||
201 | "license": [ | ||
202 | "MIT" | ||
203 | ], | ||
204 | "authors": [ | ||
205 | { | ||
206 | "name": "Fabien Potencier", | ||
207 | "email": "fabien@symfony.com" | ||
208 | } | ||
209 | ], | ||
210 | "description": "Pimple, a simple Dependency Injection Container", | ||
211 | "homepage": "http://pimple.sensiolabs.org", | ||
212 | "keywords": [ | ||
213 | "container", | ||
214 | "dependency injection" | ||
215 | ], | ||
216 | "time": "2015-09-11T15:10:35+00:00" | ||
217 | }, | ||
218 | { | ||
219 | "name": "psr/container", | ||
220 | "version": "1.0.0", | ||
221 | "source": { | ||
222 | "type": "git", | ||
223 | "url": "https://github.com/php-fig/container.git", | ||
224 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" | ||
225 | }, | ||
226 | "dist": { | ||
227 | "type": "zip", | ||
228 | "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", | ||
229 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", | ||
230 | "shasum": "" | ||
231 | }, | ||
232 | "require": { | ||
233 | "php": ">=5.3.0" | ||
234 | }, | ||
235 | "type": "library", | ||
236 | "extra": { | ||
237 | "branch-alias": { | ||
238 | "dev-master": "1.0.x-dev" | ||
239 | } | ||
240 | }, | ||
241 | "autoload": { | ||
242 | "psr-4": { | ||
243 | "Psr\\Container\\": "src/" | ||
244 | } | ||
245 | }, | ||
246 | "notification-url": "https://packagist.org/downloads/", | ||
247 | "license": [ | ||
248 | "MIT" | ||
249 | ], | ||
250 | "authors": [ | ||
251 | { | ||
252 | "name": "PHP-FIG", | ||
253 | "homepage": "http://www.php-fig.org/" | ||
254 | } | ||
255 | ], | ||
256 | "description": "Common Container Interface (PHP FIG PSR-11)", | ||
257 | "homepage": "https://github.com/php-fig/container", | ||
258 | "keywords": [ | ||
259 | "PSR-11", | ||
260 | "container", | ||
261 | "container-interface", | ||
262 | "container-interop", | ||
263 | "psr" | ||
264 | ], | ||
265 | "time": "2017-02-14T16:28:37+00:00" | ||
266 | }, | ||
267 | { | ||
268 | "name": "psr/http-message", | ||
269 | "version": "1.0.1", | ||
270 | "source": { | ||
271 | "type": "git", | ||
272 | "url": "https://github.com/php-fig/http-message.git", | ||
273 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" | ||
274 | }, | ||
275 | "dist": { | ||
276 | "type": "zip", | ||
277 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", | ||
278 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", | ||
279 | "shasum": "" | ||
280 | }, | ||
281 | "require": { | ||
282 | "php": ">=5.3.0" | ||
283 | }, | ||
284 | "type": "library", | ||
285 | "extra": { | ||
286 | "branch-alias": { | ||
287 | "dev-master": "1.0.x-dev" | ||
288 | } | ||
289 | }, | ||
290 | "autoload": { | ||
291 | "psr-4": { | ||
292 | "Psr\\Http\\Message\\": "src/" | ||
293 | } | ||
294 | }, | ||
295 | "notification-url": "https://packagist.org/downloads/", | ||
296 | "license": [ | ||
297 | "MIT" | ||
298 | ], | ||
299 | "authors": [ | ||
300 | { | ||
301 | "name": "PHP-FIG", | ||
302 | "homepage": "http://www.php-fig.org/" | ||
303 | } | ||
304 | ], | ||
305 | "description": "Common interface for HTTP messages", | ||
306 | "homepage": "https://github.com/php-fig/http-message", | ||
307 | "keywords": [ | ||
308 | "http", | ||
309 | "http-message", | ||
310 | "psr", | ||
311 | "psr-7", | ||
312 | "request", | ||
313 | "response" | ||
314 | ], | ||
315 | "time": "2016-08-06T14:39:51+00:00" | ||
316 | }, | ||
317 | { | ||
318 | "name": "psr/log", | ||
319 | "version": "1.0.2", | ||
320 | "source": { | ||
321 | "type": "git", | ||
322 | "url": "https://github.com/php-fig/log.git", | ||
323 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" | ||
324 | }, | ||
325 | "dist": { | ||
326 | "type": "zip", | ||
327 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", | ||
328 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", | ||
329 | "shasum": "" | ||
330 | }, | ||
331 | "require": { | ||
332 | "php": ">=5.3.0" | ||
333 | }, | ||
334 | "type": "library", | ||
335 | "extra": { | ||
336 | "branch-alias": { | ||
337 | "dev-master": "1.0.x-dev" | ||
338 | } | ||
339 | }, | ||
340 | "autoload": { | ||
341 | "psr-4": { | ||
342 | "Psr\\Log\\": "Psr/Log/" | ||
343 | } | ||
344 | }, | ||
345 | "notification-url": "https://packagist.org/downloads/", | ||
346 | "license": [ | ||
347 | "MIT" | ||
348 | ], | ||
349 | "authors": [ | ||
350 | { | ||
351 | "name": "PHP-FIG", | ||
352 | "homepage": "http://www.php-fig.org/" | ||
353 | } | ||
354 | ], | ||
355 | "description": "Common interface for logging libraries", | ||
356 | "homepage": "https://github.com/php-fig/log", | ||
357 | "keywords": [ | ||
358 | "log", | ||
359 | "psr", | ||
360 | "psr-3" | ||
361 | ], | ||
362 | "time": "2016-10-10T12:19:37+00:00" | ||
363 | }, | ||
364 | { | ||
365 | "name": "pubsubhubbub/publisher", | ||
366 | "version": "dev-master", | ||
367 | "source": { | ||
368 | "type": "git", | ||
369 | "url": "https://github.com/pubsubhubbub/php-publisher.git", | ||
370 | "reference": "a5d6a0e1cc9d49101c3904480e5b06cbb8addba7" | ||
371 | }, | ||
372 | "dist": { | ||
373 | "type": "zip", | ||
374 | "url": "https://api.github.com/repos/pubsubhubbub/php-publisher/zipball/a5d6a0e1cc9d49101c3904480e5b06cbb8addba7", | ||
375 | "reference": "a5d6a0e1cc9d49101c3904480e5b06cbb8addba7", | ||
376 | "shasum": "" | ||
377 | }, | ||
378 | "require": { | ||
379 | "php": "~5.4 || ~7.0" | ||
380 | }, | ||
381 | "type": "library", | ||
382 | "autoload": { | ||
383 | "psr-4": { | ||
384 | "pubsubhubbub\\publisher\\": "library/" | ||
385 | } | ||
386 | }, | ||
387 | "notification-url": "https://packagist.org/downloads/", | ||
388 | "license": [ | ||
389 | "Apache-2.0" | ||
390 | ], | ||
391 | "authors": [ | ||
392 | { | ||
393 | "name": "pubsubhubbub publisher Contributors", | ||
394 | "homepage": "https://github.com/pubsubhubbub/php-publisher/contributors" | ||
395 | } | ||
396 | ], | ||
397 | "description": "pubsubhubbub implementation of publisher.", | ||
398 | "homepage": "https://github.com/pubsubhubbub/php-publisher", | ||
399 | "keywords": [ | ||
400 | "data", | ||
401 | "feeds", | ||
402 | "publishers", | ||
403 | "pubsubhubbub" | ||
404 | ], | ||
405 | "time": "2016-11-15 06:24:01" | ||
406 | }, | ||
407 | { | ||
408 | "name": "shaarli/netscape-bookmark-parser", | ||
409 | "version": "v2.0.1", | ||
410 | "source": { | ||
411 | "type": "git", | ||
412 | "url": "https://github.com/shaarli/netscape-bookmark-parser.git", | ||
413 | "reference": "b65c7235d490bd933cdd5f71520dae656253adb9" | ||
414 | }, | ||
415 | "dist": { | ||
416 | "type": "zip", | ||
417 | "url": "https://api.github.com/repos/shaarli/netscape-bookmark-parser/zipball/b65c7235d490bd933cdd5f71520dae656253adb9", | ||
418 | "reference": "b65c7235d490bd933cdd5f71520dae656253adb9", | ||
419 | "shasum": "" | ||
420 | }, | ||
421 | "require": { | ||
422 | "katzgrau/klogger": "~1.0", | ||
423 | "php": ">=5.3.4" | ||
424 | }, | ||
425 | "require-dev": { | ||
426 | "phpunit/phpunit": "4.8.*" | ||
427 | }, | ||
428 | "type": "library", | ||
429 | "autoload": { | ||
430 | "files": [ | ||
431 | "NetscapeBookmarkParser.php" | ||
432 | ] | ||
433 | }, | ||
434 | "notification-url": "https://packagist.org/downloads/", | ||
435 | "license": [ | ||
436 | "MIT" | ||
437 | ], | ||
438 | "authors": [ | ||
439 | { | ||
440 | "name": "Kafene", | ||
441 | "email": "io@kafene.org", | ||
442 | "homepage": "https://github.com/kafene", | ||
443 | "role": "Developer" | ||
444 | }, | ||
445 | { | ||
446 | "name": "VirtualTam", | ||
447 | "email": "virtualtam@flibidi.net", | ||
448 | "homepage": "https://github.com/virtualtam", | ||
449 | "role": "Developer" | ||
450 | } | ||
451 | ], | ||
452 | "description": "Generic Netscape bookmark parser", | ||
453 | "homepage": "https://github.com/shaarli/netscape-bookmark-parser", | ||
454 | "keywords": [ | ||
455 | "bookmark", | ||
456 | "link", | ||
457 | "netscape", | ||
458 | "parse" | ||
459 | ], | ||
460 | "time": "2017-03-08T20:11:40+00:00" | ||
461 | }, | ||
462 | { | ||
463 | "name": "slim/slim", | ||
464 | "version": "3.8.1", | ||
465 | "source": { | ||
466 | "type": "git", | ||
467 | "url": "https://github.com/slimphp/Slim.git", | ||
468 | "reference": "5385302707530b2bccee1769613ad769859b826d" | ||
469 | }, | ||
470 | "dist": { | ||
471 | "type": "zip", | ||
472 | "url": "https://api.github.com/repos/slimphp/Slim/zipball/5385302707530b2bccee1769613ad769859b826d", | ||
473 | "reference": "5385302707530b2bccee1769613ad769859b826d", | ||
474 | "shasum": "" | ||
475 | }, | ||
476 | "require": { | ||
477 | "container-interop/container-interop": "^1.2", | ||
478 | "nikic/fast-route": "^1.0", | ||
479 | "php": ">=5.5.0", | ||
480 | "pimple/pimple": "^3.0", | ||
481 | "psr/container": "^1.0", | ||
482 | "psr/http-message": "^1.0" | ||
483 | }, | ||
484 | "provide": { | ||
485 | "psr/http-message-implementation": "1.0" | ||
486 | }, | ||
487 | "require-dev": { | ||
488 | "phpunit/phpunit": "^4.0", | ||
489 | "squizlabs/php_codesniffer": "^2.5" | ||
490 | }, | ||
491 | "type": "library", | ||
492 | "autoload": { | ||
493 | "psr-4": { | ||
494 | "Slim\\": "Slim" | ||
495 | } | ||
496 | }, | ||
497 | "notification-url": "https://packagist.org/downloads/", | ||
498 | "license": [ | ||
499 | "MIT" | ||
500 | ], | ||
501 | "authors": [ | ||
502 | { | ||
503 | "name": "Rob Allen", | ||
504 | "email": "rob@akrabat.com", | ||
505 | "homepage": "http://akrabat.com" | ||
506 | }, | ||
507 | { | ||
508 | "name": "Josh Lockhart", | ||
509 | "email": "hello@joshlockhart.com", | ||
510 | "homepage": "https://joshlockhart.com" | ||
511 | }, | ||
512 | { | ||
513 | "name": "Gabriel Manricks", | ||
514 | "email": "gmanricks@me.com", | ||
515 | "homepage": "http://gabrielmanricks.com" | ||
516 | }, | ||
517 | { | ||
518 | "name": "Andrew Smith", | ||
519 | "email": "a.smith@silentworks.co.uk", | ||
520 | "homepage": "http://silentworks.co.uk" | ||
521 | } | ||
522 | ], | ||
523 | "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", | ||
524 | "homepage": "https://slimframework.com", | ||
525 | "keywords": [ | ||
526 | "api", | ||
527 | "framework", | ||
528 | "micro", | ||
529 | "router" | ||
530 | ], | ||
531 | "time": "2017-03-19T17:55:20+00:00" | ||
532 | } | ||
533 | ], | ||
534 | "packages-dev": [ | ||
535 | { | ||
536 | "name": "doctrine/instantiator", | ||
537 | "version": "1.0.5", | ||
538 | "source": { | ||
539 | "type": "git", | ||
540 | "url": "https://github.com/doctrine/instantiator.git", | ||
541 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" | ||
542 | }, | ||
543 | "dist": { | ||
544 | "type": "zip", | ||
545 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", | ||
546 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", | ||
547 | "shasum": "" | ||
548 | }, | ||
549 | "require": { | ||
550 | "php": ">=5.3,<8.0-DEV" | ||
551 | }, | ||
552 | "require-dev": { | ||
553 | "athletic/athletic": "~0.1.8", | ||
554 | "ext-pdo": "*", | ||
555 | "ext-phar": "*", | ||
556 | "phpunit/phpunit": "~4.0", | ||
557 | "squizlabs/php_codesniffer": "~2.0" | ||
558 | }, | ||
559 | "type": "library", | ||
560 | "extra": { | ||
561 | "branch-alias": { | ||
562 | "dev-master": "1.0.x-dev" | ||
563 | } | ||
564 | }, | ||
565 | "autoload": { | ||
566 | "psr-4": { | ||
567 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" | ||
568 | } | ||
569 | }, | ||
570 | "notification-url": "https://packagist.org/downloads/", | ||
571 | "license": [ | ||
572 | "MIT" | ||
573 | ], | ||
574 | "authors": [ | ||
575 | { | ||
576 | "name": "Marco Pivetta", | ||
577 | "email": "ocramius@gmail.com", | ||
578 | "homepage": "http://ocramius.github.com/" | ||
579 | } | ||
580 | ], | ||
581 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", | ||
582 | "homepage": "https://github.com/doctrine/instantiator", | ||
583 | "keywords": [ | ||
584 | "constructor", | ||
585 | "instantiate" | ||
586 | ], | ||
587 | "time": "2015-06-14T21:17:01+00:00" | ||
588 | }, | ||
589 | { | ||
590 | "name": "pdepend/pdepend", | ||
591 | "version": "2.5.0", | ||
592 | "source": { | ||
593 | "type": "git", | ||
594 | "url": "https://github.com/pdepend/pdepend.git", | ||
595 | "reference": "0c50874333149c0dad5a2877801aed148f2767ff" | ||
596 | }, | ||
597 | "dist": { | ||
598 | "type": "zip", | ||
599 | "url": "https://api.github.com/repos/pdepend/pdepend/zipball/0c50874333149c0dad5a2877801aed148f2767ff", | ||
600 | "reference": "0c50874333149c0dad5a2877801aed148f2767ff", | ||
601 | "shasum": "" | ||
602 | }, | ||
603 | "require": { | ||
604 | "php": ">=5.3.7", | ||
605 | "symfony/config": "^2.3.0|^3", | ||
606 | "symfony/dependency-injection": "^2.3.0|^3", | ||
607 | "symfony/filesystem": "^2.3.0|^3" | ||
608 | }, | ||
609 | "require-dev": { | ||
610 | "phpunit/phpunit": "^4.4.0,<4.8", | ||
611 | "squizlabs/php_codesniffer": "^2.0.0" | ||
612 | }, | ||
613 | "bin": [ | ||
614 | "src/bin/pdepend" | ||
615 | ], | ||
616 | "type": "library", | ||
617 | "autoload": { | ||
618 | "psr-4": { | ||
619 | "PDepend\\": "src/main/php/PDepend" | ||
620 | } | ||
621 | }, | ||
622 | "notification-url": "https://packagist.org/downloads/", | ||
623 | "license": [ | ||
624 | "BSD-3-Clause" | ||
625 | ], | ||
626 | "description": "Official version of pdepend to be handled with Composer", | ||
627 | "time": "2017-01-19T14:23:36+00:00" | ||
628 | }, | ||
629 | { | ||
630 | "name": "phpdocumentor/reflection-common", | ||
631 | "version": "1.0", | ||
632 | "source": { | ||
633 | "type": "git", | ||
634 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", | ||
635 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" | ||
636 | }, | ||
637 | "dist": { | ||
638 | "type": "zip", | ||
639 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", | ||
640 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", | ||
641 | "shasum": "" | ||
642 | }, | ||
643 | "require": { | ||
644 | "php": ">=5.5" | ||
645 | }, | ||
646 | "require-dev": { | ||
647 | "phpunit/phpunit": "^4.6" | ||
648 | }, | ||
649 | "type": "library", | ||
650 | "extra": { | ||
651 | "branch-alias": { | ||
652 | "dev-master": "1.0.x-dev" | ||
653 | } | ||
654 | }, | ||
655 | "autoload": { | ||
656 | "psr-4": { | ||
657 | "phpDocumentor\\Reflection\\": [ | ||
658 | "src" | ||
659 | ] | ||
660 | } | ||
661 | }, | ||
662 | "notification-url": "https://packagist.org/downloads/", | ||
663 | "license": [ | ||
664 | "MIT" | ||
665 | ], | ||
666 | "authors": [ | ||
667 | { | ||
668 | "name": "Jaap van Otterdijk", | ||
669 | "email": "opensource@ijaap.nl" | ||
670 | } | ||
671 | ], | ||
672 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", | ||
673 | "homepage": "http://www.phpdoc.org", | ||
674 | "keywords": [ | ||
675 | "FQSEN", | ||
676 | "phpDocumentor", | ||
677 | "phpdoc", | ||
678 | "reflection", | ||
679 | "static analysis" | ||
680 | ], | ||
681 | "time": "2015-12-27T11:43:31+00:00" | ||
682 | }, | ||
683 | { | ||
684 | "name": "phpdocumentor/reflection-docblock", | ||
685 | "version": "3.1.1", | ||
686 | "source": { | ||
687 | "type": "git", | ||
688 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", | ||
689 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" | ||
690 | }, | ||
691 | "dist": { | ||
692 | "type": "zip", | ||
693 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", | ||
694 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", | ||
695 | "shasum": "" | ||
696 | }, | ||
697 | "require": { | ||
698 | "php": ">=5.5", | ||
699 | "phpdocumentor/reflection-common": "^1.0@dev", | ||
700 | "phpdocumentor/type-resolver": "^0.2.0", | ||
701 | "webmozart/assert": "^1.0" | ||
702 | }, | ||
703 | "require-dev": { | ||
704 | "mockery/mockery": "^0.9.4", | ||
705 | "phpunit/phpunit": "^4.4" | ||
706 | }, | ||
707 | "type": "library", | ||
708 | "autoload": { | ||
709 | "psr-4": { | ||
710 | "phpDocumentor\\Reflection\\": [ | ||
711 | "src/" | ||
712 | ] | ||
713 | } | ||
714 | }, | ||
715 | "notification-url": "https://packagist.org/downloads/", | ||
716 | "license": [ | ||
717 | "MIT" | ||
718 | ], | ||
719 | "authors": [ | ||
720 | { | ||
721 | "name": "Mike van Riel", | ||
722 | "email": "me@mikevanriel.com" | ||
723 | } | ||
724 | ], | ||
725 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", | ||
726 | "time": "2016-09-30T07:12:33+00:00" | ||
727 | }, | ||
728 | { | ||
729 | "name": "phpdocumentor/type-resolver", | ||
730 | "version": "0.2.1", | ||
731 | "source": { | ||
732 | "type": "git", | ||
733 | "url": "https://github.com/phpDocumentor/TypeResolver.git", | ||
734 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" | ||
735 | }, | ||
736 | "dist": { | ||
737 | "type": "zip", | ||
738 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", | ||
739 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", | ||
740 | "shasum": "" | ||
741 | }, | ||
742 | "require": { | ||
743 | "php": ">=5.5", | ||
744 | "phpdocumentor/reflection-common": "^1.0" | ||
745 | }, | ||
746 | "require-dev": { | ||
747 | "mockery/mockery": "^0.9.4", | ||
748 | "phpunit/phpunit": "^5.2||^4.8.24" | ||
749 | }, | ||
750 | "type": "library", | ||
751 | "extra": { | ||
752 | "branch-alias": { | ||
753 | "dev-master": "1.0.x-dev" | ||
754 | } | ||
755 | }, | ||
756 | "autoload": { | ||
757 | "psr-4": { | ||
758 | "phpDocumentor\\Reflection\\": [ | ||
759 | "src/" | ||
760 | ] | ||
761 | } | ||
762 | }, | ||
763 | "notification-url": "https://packagist.org/downloads/", | ||
764 | "license": [ | ||
765 | "MIT" | ||
766 | ], | ||
767 | "authors": [ | ||
768 | { | ||
769 | "name": "Mike van Riel", | ||
770 | "email": "me@mikevanriel.com" | ||
771 | } | ||
772 | ], | ||
773 | "time": "2016-11-25T06:54:22+00:00" | ||
774 | }, | ||
775 | { | ||
776 | "name": "phpmd/phpmd", | ||
777 | "version": "2.6.0", | ||
778 | "source": { | ||
779 | "type": "git", | ||
780 | "url": "https://github.com/phpmd/phpmd.git", | ||
781 | "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374" | ||
782 | }, | ||
783 | "dist": { | ||
784 | "type": "zip", | ||
785 | "url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374", | ||
786 | "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374", | ||
787 | "shasum": "" | ||
788 | }, | ||
789 | "require": { | ||
790 | "ext-xml": "*", | ||
791 | "pdepend/pdepend": "^2.5", | ||
792 | "php": ">=5.3.9" | ||
793 | }, | ||
794 | "require-dev": { | ||
795 | "phpunit/phpunit": "^4.0", | ||
796 | "squizlabs/php_codesniffer": "^2.0" | ||
797 | }, | ||
798 | "bin": [ | ||
799 | "src/bin/phpmd" | ||
800 | ], | ||
801 | "type": "project", | ||
802 | "autoload": { | ||
803 | "psr-0": { | ||
804 | "PHPMD\\": "src/main/php" | ||
805 | } | ||
806 | }, | ||
807 | "notification-url": "https://packagist.org/downloads/", | ||
808 | "license": [ | ||
809 | "BSD-3-Clause" | ||
810 | ], | ||
811 | "authors": [ | ||
812 | { | ||
813 | "name": "Manuel Pichler", | ||
814 | "email": "github@manuel-pichler.de", | ||
815 | "homepage": "https://github.com/manuelpichler", | ||
816 | "role": "Project Founder" | ||
817 | }, | ||
818 | { | ||
819 | "name": "Other contributors", | ||
820 | "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", | ||
821 | "role": "Contributors" | ||
822 | }, | ||
823 | { | ||
824 | "name": "Marc Würth", | ||
825 | "email": "ravage@bluewin.ch", | ||
826 | "homepage": "https://github.com/ravage84", | ||
827 | "role": "Project Maintainer" | ||
828 | } | ||
829 | ], | ||
830 | "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", | ||
831 | "homepage": "http://phpmd.org/", | ||
832 | "keywords": [ | ||
833 | "mess detection", | ||
834 | "mess detector", | ||
835 | "pdepend", | ||
836 | "phpmd", | ||
837 | "pmd" | ||
838 | ], | ||
839 | "time": "2017-01-20T14:41:10+00:00" | ||
840 | }, | ||
841 | { | ||
842 | "name": "phpspec/prophecy", | ||
843 | "version": "v1.7.0", | ||
844 | "source": { | ||
845 | "type": "git", | ||
846 | "url": "https://github.com/phpspec/prophecy.git", | ||
847 | "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" | ||
848 | }, | ||
849 | "dist": { | ||
850 | "type": "zip", | ||
851 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", | ||
852 | "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", | ||
853 | "shasum": "" | ||
854 | }, | ||
855 | "require": { | ||
856 | "doctrine/instantiator": "^1.0.2", | ||
857 | "php": "^5.3|^7.0", | ||
858 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", | ||
859 | "sebastian/comparator": "^1.1|^2.0", | ||
860 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" | ||
861 | }, | ||
862 | "require-dev": { | ||
863 | "phpspec/phpspec": "^2.5|^3.2", | ||
864 | "phpunit/phpunit": "^4.8 || ^5.6.5" | ||
865 | }, | ||
866 | "type": "library", | ||
867 | "extra": { | ||
868 | "branch-alias": { | ||
869 | "dev-master": "1.6.x-dev" | ||
870 | } | ||
871 | }, | ||
872 | "autoload": { | ||
873 | "psr-0": { | ||
874 | "Prophecy\\": "src/" | ||
875 | } | ||
876 | }, | ||
877 | "notification-url": "https://packagist.org/downloads/", | ||
878 | "license": [ | ||
879 | "MIT" | ||
880 | ], | ||
881 | "authors": [ | ||
882 | { | ||
883 | "name": "Konstantin Kudryashov", | ||
884 | "email": "ever.zet@gmail.com", | ||
885 | "homepage": "http://everzet.com" | ||
886 | }, | ||
887 | { | ||
888 | "name": "Marcello Duarte", | ||
889 | "email": "marcello.duarte@gmail.com" | ||
890 | } | ||
891 | ], | ||
892 | "description": "Highly opinionated mocking framework for PHP 5.3+", | ||
893 | "homepage": "https://github.com/phpspec/prophecy", | ||
894 | "keywords": [ | ||
895 | "Double", | ||
896 | "Dummy", | ||
897 | "fake", | ||
898 | "mock", | ||
899 | "spy", | ||
900 | "stub" | ||
901 | ], | ||
902 | "time": "2017-03-02T20:05:34+00:00" | ||
903 | }, | ||
904 | { | ||
905 | "name": "phpunit/php-code-coverage", | ||
906 | "version": "2.2.4", | ||
907 | "source": { | ||
908 | "type": "git", | ||
909 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", | ||
910 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" | ||
911 | }, | ||
912 | "dist": { | ||
913 | "type": "zip", | ||
914 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", | ||
915 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", | ||
916 | "shasum": "" | ||
917 | }, | ||
918 | "require": { | ||
919 | "php": ">=5.3.3", | ||
920 | "phpunit/php-file-iterator": "~1.3", | ||
921 | "phpunit/php-text-template": "~1.2", | ||
922 | "phpunit/php-token-stream": "~1.3", | ||
923 | "sebastian/environment": "^1.3.2", | ||
924 | "sebastian/version": "~1.0" | ||
925 | }, | ||
926 | "require-dev": { | ||
927 | "ext-xdebug": ">=2.1.4", | ||
928 | "phpunit/phpunit": "~4" | ||
929 | }, | ||
930 | "suggest": { | ||
931 | "ext-dom": "*", | ||
932 | "ext-xdebug": ">=2.2.1", | ||
933 | "ext-xmlwriter": "*" | ||
934 | }, | ||
935 | "type": "library", | ||
936 | "extra": { | ||
937 | "branch-alias": { | ||
938 | "dev-master": "2.2.x-dev" | ||
939 | } | ||
940 | }, | ||
941 | "autoload": { | ||
942 | "classmap": [ | ||
943 | "src/" | ||
944 | ] | ||
945 | }, | ||
946 | "notification-url": "https://packagist.org/downloads/", | ||
947 | "license": [ | ||
948 | "BSD-3-Clause" | ||
949 | ], | ||
950 | "authors": [ | ||
951 | { | ||
952 | "name": "Sebastian Bergmann", | ||
953 | "email": "sb@sebastian-bergmann.de", | ||
954 | "role": "lead" | ||
955 | } | ||
956 | ], | ||
957 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", | ||
958 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", | ||
959 | "keywords": [ | ||
960 | "coverage", | ||
961 | "testing", | ||
962 | "xunit" | ||
963 | ], | ||
964 | "time": "2015-10-06T15:47:00+00:00" | ||
965 | }, | ||
966 | { | ||
967 | "name": "phpunit/php-file-iterator", | ||
968 | "version": "1.4.2", | ||
969 | "source": { | ||
970 | "type": "git", | ||
971 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", | ||
972 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" | ||
973 | }, | ||
974 | "dist": { | ||
975 | "type": "zip", | ||
976 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", | ||
977 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", | ||
978 | "shasum": "" | ||
979 | }, | ||
980 | "require": { | ||
981 | "php": ">=5.3.3" | ||
982 | }, | ||
983 | "type": "library", | ||
984 | "extra": { | ||
985 | "branch-alias": { | ||
986 | "dev-master": "1.4.x-dev" | ||
987 | } | ||
988 | }, | ||
989 | "autoload": { | ||
990 | "classmap": [ | ||
991 | "src/" | ||
992 | ] | ||
993 | }, | ||
994 | "notification-url": "https://packagist.org/downloads/", | ||
995 | "license": [ | ||
996 | "BSD-3-Clause" | ||
997 | ], | ||
998 | "authors": [ | ||
999 | { | ||
1000 | "name": "Sebastian Bergmann", | ||
1001 | "email": "sb@sebastian-bergmann.de", | ||
1002 | "role": "lead" | ||
1003 | } | ||
1004 | ], | ||
1005 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", | ||
1006 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", | ||
1007 | "keywords": [ | ||
1008 | "filesystem", | ||
1009 | "iterator" | ||
1010 | ], | ||
1011 | "time": "2016-10-03T07:40:28+00:00" | ||
1012 | }, | ||
1013 | { | ||
1014 | "name": "phpunit/php-text-template", | ||
1015 | "version": "1.2.1", | ||
1016 | "source": { | ||
1017 | "type": "git", | ||
1018 | "url": "https://github.com/sebastianbergmann/php-text-template.git", | ||
1019 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" | ||
1020 | }, | ||
1021 | "dist": { | ||
1022 | "type": "zip", | ||
1023 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", | ||
1024 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", | ||
1025 | "shasum": "" | ||
1026 | }, | ||
1027 | "require": { | ||
1028 | "php": ">=5.3.3" | ||
1029 | }, | ||
1030 | "type": "library", | ||
1031 | "autoload": { | ||
1032 | "classmap": [ | ||
1033 | "src/" | ||
1034 | ] | ||
1035 | }, | ||
1036 | "notification-url": "https://packagist.org/downloads/", | ||
1037 | "license": [ | ||
1038 | "BSD-3-Clause" | ||
1039 | ], | ||
1040 | "authors": [ | ||
1041 | { | ||
1042 | "name": "Sebastian Bergmann", | ||
1043 | "email": "sebastian@phpunit.de", | ||
1044 | "role": "lead" | ||
1045 | } | ||
1046 | ], | ||
1047 | "description": "Simple template engine.", | ||
1048 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", | ||
1049 | "keywords": [ | ||
1050 | "template" | ||
1051 | ], | ||
1052 | "time": "2015-06-21T13:50:34+00:00" | ||
1053 | }, | ||
1054 | { | ||
1055 | "name": "phpunit/php-timer", | ||
1056 | "version": "1.0.9", | ||
1057 | "source": { | ||
1058 | "type": "git", | ||
1059 | "url": "https://github.com/sebastianbergmann/php-timer.git", | ||
1060 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" | ||
1061 | }, | ||
1062 | "dist": { | ||
1063 | "type": "zip", | ||
1064 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", | ||
1065 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", | ||
1066 | "shasum": "" | ||
1067 | }, | ||
1068 | "require": { | ||
1069 | "php": "^5.3.3 || ^7.0" | ||
1070 | }, | ||
1071 | "require-dev": { | ||
1072 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" | ||
1073 | }, | ||
1074 | "type": "library", | ||
1075 | "extra": { | ||
1076 | "branch-alias": { | ||
1077 | "dev-master": "1.0-dev" | ||
1078 | } | ||
1079 | }, | ||
1080 | "autoload": { | ||
1081 | "classmap": [ | ||
1082 | "src/" | ||
1083 | ] | ||
1084 | }, | ||
1085 | "notification-url": "https://packagist.org/downloads/", | ||
1086 | "license": [ | ||
1087 | "BSD-3-Clause" | ||
1088 | ], | ||
1089 | "authors": [ | ||
1090 | { | ||
1091 | "name": "Sebastian Bergmann", | ||
1092 | "email": "sb@sebastian-bergmann.de", | ||
1093 | "role": "lead" | ||
1094 | } | ||
1095 | ], | ||
1096 | "description": "Utility class for timing", | ||
1097 | "homepage": "https://github.com/sebastianbergmann/php-timer/", | ||
1098 | "keywords": [ | ||
1099 | "timer" | ||
1100 | ], | ||
1101 | "time": "2017-02-26T11:10:40+00:00" | ||
1102 | }, | ||
1103 | { | ||
1104 | "name": "phpunit/php-token-stream", | ||
1105 | "version": "1.4.11", | ||
1106 | "source": { | ||
1107 | "type": "git", | ||
1108 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", | ||
1109 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" | ||
1110 | }, | ||
1111 | "dist": { | ||
1112 | "type": "zip", | ||
1113 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", | ||
1114 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", | ||
1115 | "shasum": "" | ||
1116 | }, | ||
1117 | "require": { | ||
1118 | "ext-tokenizer": "*", | ||
1119 | "php": ">=5.3.3" | ||
1120 | }, | ||
1121 | "require-dev": { | ||
1122 | "phpunit/phpunit": "~4.2" | ||
1123 | }, | ||
1124 | "type": "library", | ||
1125 | "extra": { | ||
1126 | "branch-alias": { | ||
1127 | "dev-master": "1.4-dev" | ||
1128 | } | ||
1129 | }, | ||
1130 | "autoload": { | ||
1131 | "classmap": [ | ||
1132 | "src/" | ||
1133 | ] | ||
1134 | }, | ||
1135 | "notification-url": "https://packagist.org/downloads/", | ||
1136 | "license": [ | ||
1137 | "BSD-3-Clause" | ||
1138 | ], | ||
1139 | "authors": [ | ||
1140 | { | ||
1141 | "name": "Sebastian Bergmann", | ||
1142 | "email": "sebastian@phpunit.de" | ||
1143 | } | ||
1144 | ], | ||
1145 | "description": "Wrapper around PHP's tokenizer extension.", | ||
1146 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", | ||
1147 | "keywords": [ | ||
1148 | "tokenizer" | ||
1149 | ], | ||
1150 | "time": "2017-02-27T10:12:30+00:00" | ||
1151 | }, | ||
1152 | { | ||
1153 | "name": "phpunit/phpcov", | ||
1154 | "version": "2.0.2", | ||
1155 | "source": { | ||
1156 | "type": "git", | ||
1157 | "url": "https://github.com/sebastianbergmann/phpcov.git", | ||
1158 | "reference": "9ef291483ff65eefd8639584d61bbfb044d747f3" | ||
1159 | }, | ||
1160 | "dist": { | ||
1161 | "type": "zip", | ||
1162 | "url": "https://api.github.com/repos/sebastianbergmann/phpcov/zipball/9ef291483ff65eefd8639584d61bbfb044d747f3", | ||
1163 | "reference": "9ef291483ff65eefd8639584d61bbfb044d747f3", | ||
1164 | "shasum": "" | ||
1165 | }, | ||
1166 | "require": { | ||
1167 | "php": ">=5.3.3", | ||
1168 | "phpunit/php-code-coverage": "~2.0", | ||
1169 | "phpunit/phpunit": ">=4.1", | ||
1170 | "sebastian/diff": "~1.1", | ||
1171 | "sebastian/finder-facade": "~1.1", | ||
1172 | "sebastian/version": "~1.0", | ||
1173 | "symfony/console": "~2.2" | ||
1174 | }, | ||
1175 | "bin": [ | ||
1176 | "phpcov" | ||
1177 | ], | ||
1178 | "type": "library", | ||
1179 | "extra": { | ||
1180 | "branch-alias": { | ||
1181 | "dev-master": "2.0.x-dev" | ||
1182 | } | ||
1183 | }, | ||
1184 | "autoload": { | ||
1185 | "classmap": [ | ||
1186 | "src/" | ||
1187 | ] | ||
1188 | }, | ||
1189 | "notification-url": "https://packagist.org/downloads/", | ||
1190 | "license": [ | ||
1191 | "BSD-3-Clause" | ||
1192 | ], | ||
1193 | "authors": [ | ||
1194 | { | ||
1195 | "name": "Sebastian Bergmann", | ||
1196 | "email": "sebastian@phpunit.de", | ||
1197 | "role": "lead" | ||
1198 | } | ||
1199 | ], | ||
1200 | "description": "CLI frontend for PHP_CodeCoverage", | ||
1201 | "homepage": "https://github.com/sebastianbergmann/phpcov", | ||
1202 | "time": "2015-10-05T09:24:23+00:00" | ||
1203 | }, | ||
1204 | { | ||
1205 | "name": "phpunit/phpunit", | ||
1206 | "version": "4.8.35", | ||
1207 | "source": { | ||
1208 | "type": "git", | ||
1209 | "url": "https://github.com/sebastianbergmann/phpunit.git", | ||
1210 | "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87" | ||
1211 | }, | ||
1212 | "dist": { | ||
1213 | "type": "zip", | ||
1214 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87", | ||
1215 | "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87", | ||
1216 | "shasum": "" | ||
1217 | }, | ||
1218 | "require": { | ||
1219 | "ext-dom": "*", | ||
1220 | "ext-json": "*", | ||
1221 | "ext-pcre": "*", | ||
1222 | "ext-reflection": "*", | ||
1223 | "ext-spl": "*", | ||
1224 | "php": ">=5.3.3", | ||
1225 | "phpspec/prophecy": "^1.3.1", | ||
1226 | "phpunit/php-code-coverage": "~2.1", | ||
1227 | "phpunit/php-file-iterator": "~1.4", | ||
1228 | "phpunit/php-text-template": "~1.2", | ||
1229 | "phpunit/php-timer": "^1.0.6", | ||
1230 | "phpunit/phpunit-mock-objects": "~2.3", | ||
1231 | "sebastian/comparator": "~1.2.2", | ||
1232 | "sebastian/diff": "~1.2", | ||
1233 | "sebastian/environment": "~1.3", | ||
1234 | "sebastian/exporter": "~1.2", | ||
1235 | "sebastian/global-state": "~1.0", | ||
1236 | "sebastian/version": "~1.0", | ||
1237 | "symfony/yaml": "~2.1|~3.0" | ||
1238 | }, | ||
1239 | "suggest": { | ||
1240 | "phpunit/php-invoker": "~1.1" | ||
1241 | }, | ||
1242 | "bin": [ | ||
1243 | "phpunit" | ||
1244 | ], | ||
1245 | "type": "library", | ||
1246 | "extra": { | ||
1247 | "branch-alias": { | ||
1248 | "dev-master": "4.8.x-dev" | ||
1249 | } | ||
1250 | }, | ||
1251 | "autoload": { | ||
1252 | "classmap": [ | ||
1253 | "src/" | ||
1254 | ] | ||
1255 | }, | ||
1256 | "notification-url": "https://packagist.org/downloads/", | ||
1257 | "license": [ | ||
1258 | "BSD-3-Clause" | ||
1259 | ], | ||
1260 | "authors": [ | ||
1261 | { | ||
1262 | "name": "Sebastian Bergmann", | ||
1263 | "email": "sebastian@phpunit.de", | ||
1264 | "role": "lead" | ||
1265 | } | ||
1266 | ], | ||
1267 | "description": "The PHP Unit Testing framework.", | ||
1268 | "homepage": "https://phpunit.de/", | ||
1269 | "keywords": [ | ||
1270 | "phpunit", | ||
1271 | "testing", | ||
1272 | "xunit" | ||
1273 | ], | ||
1274 | "time": "2017-02-06T05:18:07+00:00" | ||
1275 | }, | ||
1276 | { | ||
1277 | "name": "phpunit/phpunit-mock-objects", | ||
1278 | "version": "2.3.8", | ||
1279 | "source": { | ||
1280 | "type": "git", | ||
1281 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", | ||
1282 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" | ||
1283 | }, | ||
1284 | "dist": { | ||
1285 | "type": "zip", | ||
1286 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", | ||
1287 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", | ||
1288 | "shasum": "" | ||
1289 | }, | ||
1290 | "require": { | ||
1291 | "doctrine/instantiator": "^1.0.2", | ||
1292 | "php": ">=5.3.3", | ||
1293 | "phpunit/php-text-template": "~1.2", | ||
1294 | "sebastian/exporter": "~1.2" | ||
1295 | }, | ||
1296 | "require-dev": { | ||
1297 | "phpunit/phpunit": "~4.4" | ||
1298 | }, | ||
1299 | "suggest": { | ||
1300 | "ext-soap": "*" | ||
1301 | }, | ||
1302 | "type": "library", | ||
1303 | "extra": { | ||
1304 | "branch-alias": { | ||
1305 | "dev-master": "2.3.x-dev" | ||
1306 | } | ||
1307 | }, | ||
1308 | "autoload": { | ||
1309 | "classmap": [ | ||
1310 | "src/" | ||
1311 | ] | ||
1312 | }, | ||
1313 | "notification-url": "https://packagist.org/downloads/", | ||
1314 | "license": [ | ||
1315 | "BSD-3-Clause" | ||
1316 | ], | ||
1317 | "authors": [ | ||
1318 | { | ||
1319 | "name": "Sebastian Bergmann", | ||
1320 | "email": "sb@sebastian-bergmann.de", | ||
1321 | "role": "lead" | ||
1322 | } | ||
1323 | ], | ||
1324 | "description": "Mock Object library for PHPUnit", | ||
1325 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", | ||
1326 | "keywords": [ | ||
1327 | "mock", | ||
1328 | "xunit" | ||
1329 | ], | ||
1330 | "time": "2015-10-02T06:51:40+00:00" | ||
1331 | }, | ||
1332 | { | ||
1333 | "name": "sebastian/comparator", | ||
1334 | "version": "1.2.4", | ||
1335 | "source": { | ||
1336 | "type": "git", | ||
1337 | "url": "https://github.com/sebastianbergmann/comparator.git", | ||
1338 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" | ||
1339 | }, | ||
1340 | "dist": { | ||
1341 | "type": "zip", | ||
1342 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", | ||
1343 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", | ||
1344 | "shasum": "" | ||
1345 | }, | ||
1346 | "require": { | ||
1347 | "php": ">=5.3.3", | ||
1348 | "sebastian/diff": "~1.2", | ||
1349 | "sebastian/exporter": "~1.2 || ~2.0" | ||
1350 | }, | ||
1351 | "require-dev": { | ||
1352 | "phpunit/phpunit": "~4.4" | ||
1353 | }, | ||
1354 | "type": "library", | ||
1355 | "extra": { | ||
1356 | "branch-alias": { | ||
1357 | "dev-master": "1.2.x-dev" | ||
1358 | } | ||
1359 | }, | ||
1360 | "autoload": { | ||
1361 | "classmap": [ | ||
1362 | "src/" | ||
1363 | ] | ||
1364 | }, | ||
1365 | "notification-url": "https://packagist.org/downloads/", | ||
1366 | "license": [ | ||
1367 | "BSD-3-Clause" | ||
1368 | ], | ||
1369 | "authors": [ | ||
1370 | { | ||
1371 | "name": "Jeff Welch", | ||
1372 | "email": "whatthejeff@gmail.com" | ||
1373 | }, | ||
1374 | { | ||
1375 | "name": "Volker Dusch", | ||
1376 | "email": "github@wallbash.com" | ||
1377 | }, | ||
1378 | { | ||
1379 | "name": "Bernhard Schussek", | ||
1380 | "email": "bschussek@2bepublished.at" | ||
1381 | }, | ||
1382 | { | ||
1383 | "name": "Sebastian Bergmann", | ||
1384 | "email": "sebastian@phpunit.de" | ||
1385 | } | ||
1386 | ], | ||
1387 | "description": "Provides the functionality to compare PHP values for equality", | ||
1388 | "homepage": "http://www.github.com/sebastianbergmann/comparator", | ||
1389 | "keywords": [ | ||
1390 | "comparator", | ||
1391 | "compare", | ||
1392 | "equality" | ||
1393 | ], | ||
1394 | "time": "2017-01-29T09:50:25+00:00" | ||
1395 | }, | ||
1396 | { | ||
1397 | "name": "sebastian/diff", | ||
1398 | "version": "1.4.1", | ||
1399 | "source": { | ||
1400 | "type": "git", | ||
1401 | "url": "https://github.com/sebastianbergmann/diff.git", | ||
1402 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" | ||
1403 | }, | ||
1404 | "dist": { | ||
1405 | "type": "zip", | ||
1406 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", | ||
1407 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", | ||
1408 | "shasum": "" | ||
1409 | }, | ||
1410 | "require": { | ||
1411 | "php": ">=5.3.3" | ||
1412 | }, | ||
1413 | "require-dev": { | ||
1414 | "phpunit/phpunit": "~4.8" | ||
1415 | }, | ||
1416 | "type": "library", | ||
1417 | "extra": { | ||
1418 | "branch-alias": { | ||
1419 | "dev-master": "1.4-dev" | ||
1420 | } | ||
1421 | }, | ||
1422 | "autoload": { | ||
1423 | "classmap": [ | ||
1424 | "src/" | ||
1425 | ] | ||
1426 | }, | ||
1427 | "notification-url": "https://packagist.org/downloads/", | ||
1428 | "license": [ | ||
1429 | "BSD-3-Clause" | ||
1430 | ], | ||
1431 | "authors": [ | ||
1432 | { | ||
1433 | "name": "Kore Nordmann", | ||
1434 | "email": "mail@kore-nordmann.de" | ||
1435 | }, | ||
1436 | { | ||
1437 | "name": "Sebastian Bergmann", | ||
1438 | "email": "sebastian@phpunit.de" | ||
1439 | } | ||
1440 | ], | ||
1441 | "description": "Diff implementation", | ||
1442 | "homepage": "https://github.com/sebastianbergmann/diff", | ||
1443 | "keywords": [ | ||
1444 | "diff" | ||
1445 | ], | ||
1446 | "time": "2015-12-08T07:14:41+00:00" | ||
1447 | }, | ||
1448 | { | ||
1449 | "name": "sebastian/environment", | ||
1450 | "version": "1.3.8", | ||
1451 | "source": { | ||
1452 | "type": "git", | ||
1453 | "url": "https://github.com/sebastianbergmann/environment.git", | ||
1454 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" | ||
1455 | }, | ||
1456 | "dist": { | ||
1457 | "type": "zip", | ||
1458 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", | ||
1459 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", | ||
1460 | "shasum": "" | ||
1461 | }, | ||
1462 | "require": { | ||
1463 | "php": "^5.3.3 || ^7.0" | ||
1464 | }, | ||
1465 | "require-dev": { | ||
1466 | "phpunit/phpunit": "^4.8 || ^5.0" | ||
1467 | }, | ||
1468 | "type": "library", | ||
1469 | "extra": { | ||
1470 | "branch-alias": { | ||
1471 | "dev-master": "1.3.x-dev" | ||
1472 | } | ||
1473 | }, | ||
1474 | "autoload": { | ||
1475 | "classmap": [ | ||
1476 | "src/" | ||
1477 | ] | ||
1478 | }, | ||
1479 | "notification-url": "https://packagist.org/downloads/", | ||
1480 | "license": [ | ||
1481 | "BSD-3-Clause" | ||
1482 | ], | ||
1483 | "authors": [ | ||
1484 | { | ||
1485 | "name": "Sebastian Bergmann", | ||
1486 | "email": "sebastian@phpunit.de" | ||
1487 | } | ||
1488 | ], | ||
1489 | "description": "Provides functionality to handle HHVM/PHP environments", | ||
1490 | "homepage": "http://www.github.com/sebastianbergmann/environment", | ||
1491 | "keywords": [ | ||
1492 | "Xdebug", | ||
1493 | "environment", | ||
1494 | "hhvm" | ||
1495 | ], | ||
1496 | "time": "2016-08-18T05:49:44+00:00" | ||
1497 | }, | ||
1498 | { | ||
1499 | "name": "sebastian/exporter", | ||
1500 | "version": "1.2.2", | ||
1501 | "source": { | ||
1502 | "type": "git", | ||
1503 | "url": "https://github.com/sebastianbergmann/exporter.git", | ||
1504 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" | ||
1505 | }, | ||
1506 | "dist": { | ||
1507 | "type": "zip", | ||
1508 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", | ||
1509 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", | ||
1510 | "shasum": "" | ||
1511 | }, | ||
1512 | "require": { | ||
1513 | "php": ">=5.3.3", | ||
1514 | "sebastian/recursion-context": "~1.0" | ||
1515 | }, | ||
1516 | "require-dev": { | ||
1517 | "ext-mbstring": "*", | ||
1518 | "phpunit/phpunit": "~4.4" | ||
1519 | }, | ||
1520 | "type": "library", | ||
1521 | "extra": { | ||
1522 | "branch-alias": { | ||
1523 | "dev-master": "1.3.x-dev" | ||
1524 | } | ||
1525 | }, | ||
1526 | "autoload": { | ||
1527 | "classmap": [ | ||
1528 | "src/" | ||
1529 | ] | ||
1530 | }, | ||
1531 | "notification-url": "https://packagist.org/downloads/", | ||
1532 | "license": [ | ||
1533 | "BSD-3-Clause" | ||
1534 | ], | ||
1535 | "authors": [ | ||
1536 | { | ||
1537 | "name": "Jeff Welch", | ||
1538 | "email": "whatthejeff@gmail.com" | ||
1539 | }, | ||
1540 | { | ||
1541 | "name": "Volker Dusch", | ||
1542 | "email": "github@wallbash.com" | ||
1543 | }, | ||
1544 | { | ||
1545 | "name": "Bernhard Schussek", | ||
1546 | "email": "bschussek@2bepublished.at" | ||
1547 | }, | ||
1548 | { | ||
1549 | "name": "Sebastian Bergmann", | ||
1550 | "email": "sebastian@phpunit.de" | ||
1551 | }, | ||
1552 | { | ||
1553 | "name": "Adam Harvey", | ||
1554 | "email": "aharvey@php.net" | ||
1555 | } | ||
1556 | ], | ||
1557 | "description": "Provides the functionality to export PHP variables for visualization", | ||
1558 | "homepage": "http://www.github.com/sebastianbergmann/exporter", | ||
1559 | "keywords": [ | ||
1560 | "export", | ||
1561 | "exporter" | ||
1562 | ], | ||
1563 | "time": "2016-06-17T09:04:28+00:00" | ||
1564 | }, | ||
1565 | { | ||
1566 | "name": "sebastian/finder-facade", | ||
1567 | "version": "1.2.1", | ||
1568 | "source": { | ||
1569 | "type": "git", | ||
1570 | "url": "https://github.com/sebastianbergmann/finder-facade.git", | ||
1571 | "reference": "2a6f7f57efc0aa2d23297d9fd9e2a03111a8c0b9" | ||
1572 | }, | ||
1573 | "dist": { | ||
1574 | "type": "zip", | ||
1575 | "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/2a6f7f57efc0aa2d23297d9fd9e2a03111a8c0b9", | ||
1576 | "reference": "2a6f7f57efc0aa2d23297d9fd9e2a03111a8c0b9", | ||
1577 | "shasum": "" | ||
1578 | }, | ||
1579 | "require": { | ||
1580 | "symfony/finder": "~2.3|~3.0", | ||
1581 | "theseer/fdomdocument": "~1.3" | ||
1582 | }, | ||
1583 | "type": "library", | ||
1584 | "autoload": { | ||
1585 | "classmap": [ | ||
1586 | "src/" | ||
1587 | ] | ||
1588 | }, | ||
1589 | "notification-url": "https://packagist.org/downloads/", | ||
1590 | "license": [ | ||
1591 | "BSD-3-Clause" | ||
1592 | ], | ||
1593 | "authors": [ | ||
1594 | { | ||
1595 | "name": "Sebastian Bergmann", | ||
1596 | "email": "sebastian@phpunit.de", | ||
1597 | "role": "lead" | ||
1598 | } | ||
1599 | ], | ||
1600 | "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", | ||
1601 | "homepage": "https://github.com/sebastianbergmann/finder-facade", | ||
1602 | "time": "2016-02-17T07:02:23+00:00" | ||
1603 | }, | ||
1604 | { | ||
1605 | "name": "sebastian/global-state", | ||
1606 | "version": "1.1.1", | ||
1607 | "source": { | ||
1608 | "type": "git", | ||
1609 | "url": "https://github.com/sebastianbergmann/global-state.git", | ||
1610 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" | ||
1611 | }, | ||
1612 | "dist": { | ||
1613 | "type": "zip", | ||
1614 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", | ||
1615 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", | ||
1616 | "shasum": "" | ||
1617 | }, | ||
1618 | "require": { | ||
1619 | "php": ">=5.3.3" | ||
1620 | }, | ||
1621 | "require-dev": { | ||
1622 | "phpunit/phpunit": "~4.2" | ||
1623 | }, | ||
1624 | "suggest": { | ||
1625 | "ext-uopz": "*" | ||
1626 | }, | ||
1627 | "type": "library", | ||
1628 | "extra": { | ||
1629 | "branch-alias": { | ||
1630 | "dev-master": "1.0-dev" | ||
1631 | } | ||
1632 | }, | ||
1633 | "autoload": { | ||
1634 | "classmap": [ | ||
1635 | "src/" | ||
1636 | ] | ||
1637 | }, | ||
1638 | "notification-url": "https://packagist.org/downloads/", | ||
1639 | "license": [ | ||
1640 | "BSD-3-Clause" | ||
1641 | ], | ||
1642 | "authors": [ | ||
1643 | { | ||
1644 | "name": "Sebastian Bergmann", | ||
1645 | "email": "sebastian@phpunit.de" | ||
1646 | } | ||
1647 | ], | ||
1648 | "description": "Snapshotting of global state", | ||
1649 | "homepage": "http://www.github.com/sebastianbergmann/global-state", | ||
1650 | "keywords": [ | ||
1651 | "global state" | ||
1652 | ], | ||
1653 | "time": "2015-10-12T03:26:01+00:00" | ||
1654 | }, | ||
1655 | { | ||
1656 | "name": "sebastian/phpcpd", | ||
1657 | "version": "2.0.4", | ||
1658 | "source": { | ||
1659 | "type": "git", | ||
1660 | "url": "https://github.com/sebastianbergmann/phpcpd.git", | ||
1661 | "reference": "24d9a880deadb0b8c9680e9cfe78e30b704225db" | ||
1662 | }, | ||
1663 | "dist": { | ||
1664 | "type": "zip", | ||
1665 | "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/24d9a880deadb0b8c9680e9cfe78e30b704225db", | ||
1666 | "reference": "24d9a880deadb0b8c9680e9cfe78e30b704225db", | ||
1667 | "shasum": "" | ||
1668 | }, | ||
1669 | "require": { | ||
1670 | "php": ">=5.3.3", | ||
1671 | "phpunit/php-timer": ">=1.0.6", | ||
1672 | "sebastian/finder-facade": "~1.1", | ||
1673 | "sebastian/version": "~1.0|~2.0", | ||
1674 | "symfony/console": "~2.7|^3.0", | ||
1675 | "theseer/fdomdocument": "~1.4" | ||
1676 | }, | ||
1677 | "bin": [ | ||
1678 | "phpcpd" | ||
1679 | ], | ||
1680 | "type": "library", | ||
1681 | "extra": { | ||
1682 | "branch-alias": { | ||
1683 | "dev-master": "2.0-dev" | ||
1684 | } | ||
1685 | }, | ||
1686 | "autoload": { | ||
1687 | "classmap": [ | ||
1688 | "src/" | ||
1689 | ] | ||
1690 | }, | ||
1691 | "notification-url": "https://packagist.org/downloads/", | ||
1692 | "license": [ | ||
1693 | "BSD-3-Clause" | ||
1694 | ], | ||
1695 | "authors": [ | ||
1696 | { | ||
1697 | "name": "Sebastian Bergmann", | ||
1698 | "email": "sebastian@phpunit.de", | ||
1699 | "role": "lead" | ||
1700 | } | ||
1701 | ], | ||
1702 | "description": "Copy/Paste Detector (CPD) for PHP code.", | ||
1703 | "homepage": "https://github.com/sebastianbergmann/phpcpd", | ||
1704 | "time": "2016-04-17T19:32:49+00:00" | ||
1705 | }, | ||
1706 | { | ||
1707 | "name": "sebastian/recursion-context", | ||
1708 | "version": "1.0.5", | ||
1709 | "source": { | ||
1710 | "type": "git", | ||
1711 | "url": "https://github.com/sebastianbergmann/recursion-context.git", | ||
1712 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" | ||
1713 | }, | ||
1714 | "dist": { | ||
1715 | "type": "zip", | ||
1716 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", | ||
1717 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", | ||
1718 | "shasum": "" | ||
1719 | }, | ||
1720 | "require": { | ||
1721 | "php": ">=5.3.3" | ||
1722 | }, | ||
1723 | "require-dev": { | ||
1724 | "phpunit/phpunit": "~4.4" | ||
1725 | }, | ||
1726 | "type": "library", | ||
1727 | "extra": { | ||
1728 | "branch-alias": { | ||
1729 | "dev-master": "1.0.x-dev" | ||
1730 | } | ||
1731 | }, | ||
1732 | "autoload": { | ||
1733 | "classmap": [ | ||
1734 | "src/" | ||
1735 | ] | ||
1736 | }, | ||
1737 | "notification-url": "https://packagist.org/downloads/", | ||
1738 | "license": [ | ||
1739 | "BSD-3-Clause" | ||
1740 | ], | ||
1741 | "authors": [ | ||
1742 | { | ||
1743 | "name": "Jeff Welch", | ||
1744 | "email": "whatthejeff@gmail.com" | ||
1745 | }, | ||
1746 | { | ||
1747 | "name": "Sebastian Bergmann", | ||
1748 | "email": "sebastian@phpunit.de" | ||
1749 | }, | ||
1750 | { | ||
1751 | "name": "Adam Harvey", | ||
1752 | "email": "aharvey@php.net" | ||
1753 | } | ||
1754 | ], | ||
1755 | "description": "Provides functionality to recursively process PHP variables", | ||
1756 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", | ||
1757 | "time": "2016-10-03T07:41:43+00:00" | ||
1758 | }, | ||
1759 | { | ||
1760 | "name": "sebastian/version", | ||
1761 | "version": "1.0.6", | ||
1762 | "source": { | ||
1763 | "type": "git", | ||
1764 | "url": "https://github.com/sebastianbergmann/version.git", | ||
1765 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" | ||
1766 | }, | ||
1767 | "dist": { | ||
1768 | "type": "zip", | ||
1769 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", | ||
1770 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", | ||
1771 | "shasum": "" | ||
1772 | }, | ||
1773 | "type": "library", | ||
1774 | "autoload": { | ||
1775 | "classmap": [ | ||
1776 | "src/" | ||
1777 | ] | ||
1778 | }, | ||
1779 | "notification-url": "https://packagist.org/downloads/", | ||
1780 | "license": [ | ||
1781 | "BSD-3-Clause" | ||
1782 | ], | ||
1783 | "authors": [ | ||
1784 | { | ||
1785 | "name": "Sebastian Bergmann", | ||
1786 | "email": "sebastian@phpunit.de", | ||
1787 | "role": "lead" | ||
1788 | } | ||
1789 | ], | ||
1790 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", | ||
1791 | "homepage": "https://github.com/sebastianbergmann/version", | ||
1792 | "time": "2015-06-21T13:59:46+00:00" | ||
1793 | }, | ||
1794 | { | ||
1795 | "name": "squizlabs/php_codesniffer", | ||
1796 | "version": "2.8.1", | ||
1797 | "source": { | ||
1798 | "type": "git", | ||
1799 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", | ||
1800 | "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d" | ||
1801 | }, | ||
1802 | "dist": { | ||
1803 | "type": "zip", | ||
1804 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", | ||
1805 | "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", | ||
1806 | "shasum": "" | ||
1807 | }, | ||
1808 | "require": { | ||
1809 | "ext-simplexml": "*", | ||
1810 | "ext-tokenizer": "*", | ||
1811 | "ext-xmlwriter": "*", | ||
1812 | "php": ">=5.1.2" | ||
1813 | }, | ||
1814 | "require-dev": { | ||
1815 | "phpunit/phpunit": "~4.0" | ||
1816 | }, | ||
1817 | "bin": [ | ||
1818 | "scripts/phpcs", | ||
1819 | "scripts/phpcbf" | ||
1820 | ], | ||
1821 | "type": "library", | ||
1822 | "extra": { | ||
1823 | "branch-alias": { | ||
1824 | "dev-master": "2.x-dev" | ||
1825 | } | ||
1826 | }, | ||
1827 | "autoload": { | ||
1828 | "classmap": [ | ||
1829 | "CodeSniffer.php", | ||
1830 | "CodeSniffer/CLI.php", | ||
1831 | "CodeSniffer/Exception.php", | ||
1832 | "CodeSniffer/File.php", | ||
1833 | "CodeSniffer/Fixer.php", | ||
1834 | "CodeSniffer/Report.php", | ||
1835 | "CodeSniffer/Reporting.php", | ||
1836 | "CodeSniffer/Sniff.php", | ||
1837 | "CodeSniffer/Tokens.php", | ||
1838 | "CodeSniffer/Reports/", | ||
1839 | "CodeSniffer/Tokenizers/", | ||
1840 | "CodeSniffer/DocGenerators/", | ||
1841 | "CodeSniffer/Standards/AbstractPatternSniff.php", | ||
1842 | "CodeSniffer/Standards/AbstractScopeSniff.php", | ||
1843 | "CodeSniffer/Standards/AbstractVariableSniff.php", | ||
1844 | "CodeSniffer/Standards/IncorrectPatternException.php", | ||
1845 | "CodeSniffer/Standards/Generic/Sniffs/", | ||
1846 | "CodeSniffer/Standards/MySource/Sniffs/", | ||
1847 | "CodeSniffer/Standards/PEAR/Sniffs/", | ||
1848 | "CodeSniffer/Standards/PSR1/Sniffs/", | ||
1849 | "CodeSniffer/Standards/PSR2/Sniffs/", | ||
1850 | "CodeSniffer/Standards/Squiz/Sniffs/", | ||
1851 | "CodeSniffer/Standards/Zend/Sniffs/" | ||
1852 | ] | ||
1853 | }, | ||
1854 | "notification-url": "https://packagist.org/downloads/", | ||
1855 | "license": [ | ||
1856 | "BSD-3-Clause" | ||
1857 | ], | ||
1858 | "authors": [ | ||
1859 | { | ||
1860 | "name": "Greg Sherwood", | ||
1861 | "role": "lead" | ||
1862 | } | ||
1863 | ], | ||
1864 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", | ||
1865 | "homepage": "http://www.squizlabs.com/php-codesniffer", | ||
1866 | "keywords": [ | ||
1867 | "phpcs", | ||
1868 | "standards" | ||
1869 | ], | ||
1870 | "time": "2017-03-01T22:17:45+00:00" | ||
1871 | }, | ||
1872 | { | ||
1873 | "name": "symfony/config", | ||
1874 | "version": "v3.2.6", | ||
1875 | "source": { | ||
1876 | "type": "git", | ||
1877 | "url": "https://github.com/symfony/config.git", | ||
1878 | "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2" | ||
1879 | }, | ||
1880 | "dist": { | ||
1881 | "type": "zip", | ||
1882 | "url": "https://api.github.com/repos/symfony/config/zipball/741d6d4cd1414d67d48eb71aba6072b46ba740c2", | ||
1883 | "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2", | ||
1884 | "shasum": "" | ||
1885 | }, | ||
1886 | "require": { | ||
1887 | "php": ">=5.5.9", | ||
1888 | "symfony/filesystem": "~2.8|~3.0" | ||
1889 | }, | ||
1890 | "require-dev": { | ||
1891 | "symfony/yaml": "~3.0" | ||
1892 | }, | ||
1893 | "suggest": { | ||
1894 | "symfony/yaml": "To use the yaml reference dumper" | ||
1895 | }, | ||
1896 | "type": "library", | ||
1897 | "extra": { | ||
1898 | "branch-alias": { | ||
1899 | "dev-master": "3.2-dev" | ||
1900 | } | ||
1901 | }, | ||
1902 | "autoload": { | ||
1903 | "psr-4": { | ||
1904 | "Symfony\\Component\\Config\\": "" | ||
1905 | }, | ||
1906 | "exclude-from-classmap": [ | ||
1907 | "/Tests/" | ||
1908 | ] | ||
1909 | }, | ||
1910 | "notification-url": "https://packagist.org/downloads/", | ||
1911 | "license": [ | ||
1912 | "MIT" | ||
1913 | ], | ||
1914 | "authors": [ | ||
1915 | { | ||
1916 | "name": "Fabien Potencier", | ||
1917 | "email": "fabien@symfony.com" | ||
1918 | }, | ||
1919 | { | ||
1920 | "name": "Symfony Community", | ||
1921 | "homepage": "https://symfony.com/contributors" | ||
1922 | } | ||
1923 | ], | ||
1924 | "description": "Symfony Config Component", | ||
1925 | "homepage": "https://symfony.com", | ||
1926 | "time": "2017-03-01T18:18:25+00:00" | ||
1927 | }, | ||
1928 | { | ||
1929 | "name": "symfony/console", | ||
1930 | "version": "v2.8.18", | ||
1931 | "source": { | ||
1932 | "type": "git", | ||
1933 | "url": "https://github.com/symfony/console.git", | ||
1934 | "reference": "81508e6fac4476771275a3f4f53c3fee9b956bfa" | ||
1935 | }, | ||
1936 | "dist": { | ||
1937 | "type": "zip", | ||
1938 | "url": "https://api.github.com/repos/symfony/console/zipball/81508e6fac4476771275a3f4f53c3fee9b956bfa", | ||
1939 | "reference": "81508e6fac4476771275a3f4f53c3fee9b956bfa", | ||
1940 | "shasum": "" | ||
1941 | }, | ||
1942 | "require": { | ||
1943 | "php": ">=5.3.9", | ||
1944 | "symfony/debug": "^2.7.2|~3.0.0", | ||
1945 | "symfony/polyfill-mbstring": "~1.0" | ||
1946 | }, | ||
1947 | "require-dev": { | ||
1948 | "psr/log": "~1.0", | ||
1949 | "symfony/event-dispatcher": "~2.1|~3.0.0", | ||
1950 | "symfony/process": "~2.1|~3.0.0" | ||
1951 | }, | ||
1952 | "suggest": { | ||
1953 | "psr/log": "For using the console logger", | ||
1954 | "symfony/event-dispatcher": "", | ||
1955 | "symfony/process": "" | ||
1956 | }, | ||
1957 | "type": "library", | ||
1958 | "extra": { | ||
1959 | "branch-alias": { | ||
1960 | "dev-master": "2.8-dev" | ||
1961 | } | ||
1962 | }, | ||
1963 | "autoload": { | ||
1964 | "psr-4": { | ||
1965 | "Symfony\\Component\\Console\\": "" | ||
1966 | }, | ||
1967 | "exclude-from-classmap": [ | ||
1968 | "/Tests/" | ||
1969 | ] | ||
1970 | }, | ||
1971 | "notification-url": "https://packagist.org/downloads/", | ||
1972 | "license": [ | ||
1973 | "MIT" | ||
1974 | ], | ||
1975 | "authors": [ | ||
1976 | { | ||
1977 | "name": "Fabien Potencier", | ||
1978 | "email": "fabien@symfony.com" | ||
1979 | }, | ||
1980 | { | ||
1981 | "name": "Symfony Community", | ||
1982 | "homepage": "https://symfony.com/contributors" | ||
1983 | } | ||
1984 | ], | ||
1985 | "description": "Symfony Console Component", | ||
1986 | "homepage": "https://symfony.com", | ||
1987 | "time": "2017-03-04T11:00:12+00:00" | ||
1988 | }, | ||
1989 | { | ||
1990 | "name": "symfony/debug", | ||
1991 | "version": "v3.0.9", | ||
1992 | "source": { | ||
1993 | "type": "git", | ||
1994 | "url": "https://github.com/symfony/debug.git", | ||
1995 | "reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a" | ||
1996 | }, | ||
1997 | "dist": { | ||
1998 | "type": "zip", | ||
1999 | "url": "https://api.github.com/repos/symfony/debug/zipball/697c527acd9ea1b2d3efac34d9806bf255278b0a", | ||
2000 | "reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a", | ||
2001 | "shasum": "" | ||
2002 | }, | ||
2003 | "require": { | ||
2004 | "php": ">=5.5.9", | ||
2005 | "psr/log": "~1.0" | ||
2006 | }, | ||
2007 | "conflict": { | ||
2008 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" | ||
2009 | }, | ||
2010 | "require-dev": { | ||
2011 | "symfony/class-loader": "~2.8|~3.0", | ||
2012 | "symfony/http-kernel": "~2.8|~3.0" | ||
2013 | }, | ||
2014 | "type": "library", | ||
2015 | "extra": { | ||
2016 | "branch-alias": { | ||
2017 | "dev-master": "3.0-dev" | ||
2018 | } | ||
2019 | }, | ||
2020 | "autoload": { | ||
2021 | "psr-4": { | ||
2022 | "Symfony\\Component\\Debug\\": "" | ||
2023 | }, | ||
2024 | "exclude-from-classmap": [ | ||
2025 | "/Tests/" | ||
2026 | ] | ||
2027 | }, | ||
2028 | "notification-url": "https://packagist.org/downloads/", | ||
2029 | "license": [ | ||
2030 | "MIT" | ||
2031 | ], | ||
2032 | "authors": [ | ||
2033 | { | ||
2034 | "name": "Fabien Potencier", | ||
2035 | "email": "fabien@symfony.com" | ||
2036 | }, | ||
2037 | { | ||
2038 | "name": "Symfony Community", | ||
2039 | "homepage": "https://symfony.com/contributors" | ||
2040 | } | ||
2041 | ], | ||
2042 | "description": "Symfony Debug Component", | ||
2043 | "homepage": "https://symfony.com", | ||
2044 | "time": "2016-07-30T07:22:48+00:00" | ||
2045 | }, | ||
2046 | { | ||
2047 | "name": "symfony/dependency-injection", | ||
2048 | "version": "v3.2.6", | ||
2049 | "source": { | ||
2050 | "type": "git", | ||
2051 | "url": "https://github.com/symfony/dependency-injection.git", | ||
2052 | "reference": "74e0935e414ad33d5e82074212c0eedb4681a691" | ||
2053 | }, | ||
2054 | "dist": { | ||
2055 | "type": "zip", | ||
2056 | "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/74e0935e414ad33d5e82074212c0eedb4681a691", | ||
2057 | "reference": "74e0935e414ad33d5e82074212c0eedb4681a691", | ||
2058 | "shasum": "" | ||
2059 | }, | ||
2060 | "require": { | ||
2061 | "php": ">=5.5.9" | ||
2062 | }, | ||
2063 | "conflict": { | ||
2064 | "symfony/yaml": "<3.2" | ||
2065 | }, | ||
2066 | "require-dev": { | ||
2067 | "symfony/config": "~2.8|~3.0", | ||
2068 | "symfony/expression-language": "~2.8|~3.0", | ||
2069 | "symfony/yaml": "~3.2" | ||
2070 | }, | ||
2071 | "suggest": { | ||
2072 | "symfony/config": "", | ||
2073 | "symfony/expression-language": "For using expressions in service container configuration", | ||
2074 | "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", | ||
2075 | "symfony/yaml": "" | ||
2076 | }, | ||
2077 | "type": "library", | ||
2078 | "extra": { | ||
2079 | "branch-alias": { | ||
2080 | "dev-master": "3.2-dev" | ||
2081 | } | ||
2082 | }, | ||
2083 | "autoload": { | ||
2084 | "psr-4": { | ||
2085 | "Symfony\\Component\\DependencyInjection\\": "" | ||
2086 | }, | ||
2087 | "exclude-from-classmap": [ | ||
2088 | "/Tests/" | ||
2089 | ] | ||
2090 | }, | ||
2091 | "notification-url": "https://packagist.org/downloads/", | ||
2092 | "license": [ | ||
2093 | "MIT" | ||
2094 | ], | ||
2095 | "authors": [ | ||
2096 | { | ||
2097 | "name": "Fabien Potencier", | ||
2098 | "email": "fabien@symfony.com" | ||
2099 | }, | ||
2100 | { | ||
2101 | "name": "Symfony Community", | ||
2102 | "homepage": "https://symfony.com/contributors" | ||
2103 | } | ||
2104 | ], | ||
2105 | "description": "Symfony DependencyInjection Component", | ||
2106 | "homepage": "https://symfony.com", | ||
2107 | "time": "2017-03-05T00:06:55+00:00" | ||
2108 | }, | ||
2109 | { | ||
2110 | "name": "symfony/filesystem", | ||
2111 | "version": "v3.2.6", | ||
2112 | "source": { | ||
2113 | "type": "git", | ||
2114 | "url": "https://github.com/symfony/filesystem.git", | ||
2115 | "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a" | ||
2116 | }, | ||
2117 | "dist": { | ||
2118 | "type": "zip", | ||
2119 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/bc0f17bed914df2cceb989972c3b996043c4da4a", | ||
2120 | "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a", | ||
2121 | "shasum": "" | ||
2122 | }, | ||
2123 | "require": { | ||
2124 | "php": ">=5.5.9" | ||
2125 | }, | ||
2126 | "type": "library", | ||
2127 | "extra": { | ||
2128 | "branch-alias": { | ||
2129 | "dev-master": "3.2-dev" | ||
2130 | } | ||
2131 | }, | ||
2132 | "autoload": { | ||
2133 | "psr-4": { | ||
2134 | "Symfony\\Component\\Filesystem\\": "" | ||
2135 | }, | ||
2136 | "exclude-from-classmap": [ | ||
2137 | "/Tests/" | ||
2138 | ] | ||
2139 | }, | ||
2140 | "notification-url": "https://packagist.org/downloads/", | ||
2141 | "license": [ | ||
2142 | "MIT" | ||
2143 | ], | ||
2144 | "authors": [ | ||
2145 | { | ||
2146 | "name": "Fabien Potencier", | ||
2147 | "email": "fabien@symfony.com" | ||
2148 | }, | ||
2149 | { | ||
2150 | "name": "Symfony Community", | ||
2151 | "homepage": "https://symfony.com/contributors" | ||
2152 | } | ||
2153 | ], | ||
2154 | "description": "Symfony Filesystem Component", | ||
2155 | "homepage": "https://symfony.com", | ||
2156 | "time": "2017-03-06T19:30:27+00:00" | ||
2157 | }, | ||
2158 | { | ||
2159 | "name": "symfony/finder", | ||
2160 | "version": "v3.2.6", | ||
2161 | "source": { | ||
2162 | "type": "git", | ||
2163 | "url": "https://github.com/symfony/finder.git", | ||
2164 | "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10" | ||
2165 | }, | ||
2166 | "dist": { | ||
2167 | "type": "zip", | ||
2168 | "url": "https://api.github.com/repos/symfony/finder/zipball/92d7476d2df60cd851a3e13e078664b1deb8ce10", | ||
2169 | "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10", | ||
2170 | "shasum": "" | ||
2171 | }, | ||
2172 | "require": { | ||
2173 | "php": ">=5.5.9" | ||
2174 | }, | ||
2175 | "type": "library", | ||
2176 | "extra": { | ||
2177 | "branch-alias": { | ||
2178 | "dev-master": "3.2-dev" | ||
2179 | } | ||
2180 | }, | ||
2181 | "autoload": { | ||
2182 | "psr-4": { | ||
2183 | "Symfony\\Component\\Finder\\": "" | ||
2184 | }, | ||
2185 | "exclude-from-classmap": [ | ||
2186 | "/Tests/" | ||
2187 | ] | ||
2188 | }, | ||
2189 | "notification-url": "https://packagist.org/downloads/", | ||
2190 | "license": [ | ||
2191 | "MIT" | ||
2192 | ], | ||
2193 | "authors": [ | ||
2194 | { | ||
2195 | "name": "Fabien Potencier", | ||
2196 | "email": "fabien@symfony.com" | ||
2197 | }, | ||
2198 | { | ||
2199 | "name": "Symfony Community", | ||
2200 | "homepage": "https://symfony.com/contributors" | ||
2201 | } | ||
2202 | ], | ||
2203 | "description": "Symfony Finder Component", | ||
2204 | "homepage": "https://symfony.com", | ||
2205 | "time": "2017-02-21T09:12:04+00:00" | ||
2206 | }, | ||
2207 | { | ||
2208 | "name": "symfony/polyfill-mbstring", | ||
2209 | "version": "v1.3.0", | ||
2210 | "source": { | ||
2211 | "type": "git", | ||
2212 | "url": "https://github.com/symfony/polyfill-mbstring.git", | ||
2213 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" | ||
2214 | }, | ||
2215 | "dist": { | ||
2216 | "type": "zip", | ||
2217 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", | ||
2218 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", | ||
2219 | "shasum": "" | ||
2220 | }, | ||
2221 | "require": { | ||
2222 | "php": ">=5.3.3" | ||
2223 | }, | ||
2224 | "suggest": { | ||
2225 | "ext-mbstring": "For best performance" | ||
2226 | }, | ||
2227 | "type": "library", | ||
2228 | "extra": { | ||
2229 | "branch-alias": { | ||
2230 | "dev-master": "1.3-dev" | ||
2231 | } | ||
2232 | }, | ||
2233 | "autoload": { | ||
2234 | "psr-4": { | ||
2235 | "Symfony\\Polyfill\\Mbstring\\": "" | ||
2236 | }, | ||
2237 | "files": [ | ||
2238 | "bootstrap.php" | ||
2239 | ] | ||
2240 | }, | ||
2241 | "notification-url": "https://packagist.org/downloads/", | ||
2242 | "license": [ | ||
2243 | "MIT" | ||
2244 | ], | ||
2245 | "authors": [ | ||
2246 | { | ||
2247 | "name": "Nicolas Grekas", | ||
2248 | "email": "p@tchwork.com" | ||
2249 | }, | ||
2250 | { | ||
2251 | "name": "Symfony Community", | ||
2252 | "homepage": "https://symfony.com/contributors" | ||
2253 | } | ||
2254 | ], | ||
2255 | "description": "Symfony polyfill for the Mbstring extension", | ||
2256 | "homepage": "https://symfony.com", | ||
2257 | "keywords": [ | ||
2258 | "compatibility", | ||
2259 | "mbstring", | ||
2260 | "polyfill", | ||
2261 | "portable", | ||
2262 | "shim" | ||
2263 | ], | ||
2264 | "time": "2016-11-14T01:06:16+00:00" | ||
2265 | }, | ||
2266 | { | ||
2267 | "name": "symfony/yaml", | ||
2268 | "version": "v3.2.6", | ||
2269 | "source": { | ||
2270 | "type": "git", | ||
2271 | "url": "https://github.com/symfony/yaml.git", | ||
2272 | "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" | ||
2273 | }, | ||
2274 | "dist": { | ||
2275 | "type": "zip", | ||
2276 | "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", | ||
2277 | "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", | ||
2278 | "shasum": "" | ||
2279 | }, | ||
2280 | "require": { | ||
2281 | "php": ">=5.5.9" | ||
2282 | }, | ||
2283 | "require-dev": { | ||
2284 | "symfony/console": "~2.8|~3.0" | ||
2285 | }, | ||
2286 | "suggest": { | ||
2287 | "symfony/console": "For validating YAML files using the lint command" | ||
2288 | }, | ||
2289 | "type": "library", | ||
2290 | "extra": { | ||
2291 | "branch-alias": { | ||
2292 | "dev-master": "3.2-dev" | ||
2293 | } | ||
2294 | }, | ||
2295 | "autoload": { | ||
2296 | "psr-4": { | ||
2297 | "Symfony\\Component\\Yaml\\": "" | ||
2298 | }, | ||
2299 | "exclude-from-classmap": [ | ||
2300 | "/Tests/" | ||
2301 | ] | ||
2302 | }, | ||
2303 | "notification-url": "https://packagist.org/downloads/", | ||
2304 | "license": [ | ||
2305 | "MIT" | ||
2306 | ], | ||
2307 | "authors": [ | ||
2308 | { | ||
2309 | "name": "Fabien Potencier", | ||
2310 | "email": "fabien@symfony.com" | ||
2311 | }, | ||
2312 | { | ||
2313 | "name": "Symfony Community", | ||
2314 | "homepage": "https://symfony.com/contributors" | ||
2315 | } | ||
2316 | ], | ||
2317 | "description": "Symfony Yaml Component", | ||
2318 | "homepage": "https://symfony.com", | ||
2319 | "time": "2017-03-07T16:47:02+00:00" | ||
2320 | }, | ||
2321 | { | ||
2322 | "name": "theseer/fdomdocument", | ||
2323 | "version": "1.6.1", | ||
2324 | "source": { | ||
2325 | "type": "git", | ||
2326 | "url": "https://github.com/theseer/fDOMDocument.git", | ||
2327 | "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684" | ||
2328 | }, | ||
2329 | "dist": { | ||
2330 | "type": "zip", | ||
2331 | "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d9ad139d6c2e8edf5e313ffbe37ff13344cf0684", | ||
2332 | "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684", | ||
2333 | "shasum": "" | ||
2334 | }, | ||
2335 | "require": { | ||
2336 | "ext-dom": "*", | ||
2337 | "lib-libxml": "*", | ||
2338 | "php": ">=5.3.3" | ||
2339 | }, | ||
2340 | "type": "library", | ||
2341 | "autoload": { | ||
2342 | "classmap": [ | ||
2343 | "src/" | ||
2344 | ] | ||
2345 | }, | ||
2346 | "notification-url": "https://packagist.org/downloads/", | ||
2347 | "license": [ | ||
2348 | "BSD-3-Clause" | ||
2349 | ], | ||
2350 | "authors": [ | ||
2351 | { | ||
2352 | "name": "Arne Blankerts", | ||
2353 | "email": "arne@blankerts.de", | ||
2354 | "role": "lead" | ||
2355 | } | ||
2356 | ], | ||
2357 | "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", | ||
2358 | "homepage": "https://github.com/theseer/fDOMDocument", | ||
2359 | "time": "2015-05-27T22:58:02+00:00" | ||
2360 | }, | ||
2361 | { | ||
2362 | "name": "webmozart/assert", | ||
2363 | "version": "1.2.0", | ||
2364 | "source": { | ||
2365 | "type": "git", | ||
2366 | "url": "https://github.com/webmozart/assert.git", | ||
2367 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" | ||
2368 | }, | ||
2369 | "dist": { | ||
2370 | "type": "zip", | ||
2371 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", | ||
2372 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", | ||
2373 | "shasum": "" | ||
2374 | }, | ||
2375 | "require": { | ||
2376 | "php": "^5.3.3 || ^7.0" | ||
2377 | }, | ||
2378 | "require-dev": { | ||
2379 | "phpunit/phpunit": "^4.6", | ||
2380 | "sebastian/version": "^1.0.1" | ||
2381 | }, | ||
2382 | "type": "library", | ||
2383 | "extra": { | ||
2384 | "branch-alias": { | ||
2385 | "dev-master": "1.3-dev" | ||
2386 | } | ||
2387 | }, | ||
2388 | "autoload": { | ||
2389 | "psr-4": { | ||
2390 | "Webmozart\\Assert\\": "src/" | ||
2391 | } | ||
2392 | }, | ||
2393 | "notification-url": "https://packagist.org/downloads/", | ||
2394 | "license": [ | ||
2395 | "MIT" | ||
2396 | ], | ||
2397 | "authors": [ | ||
2398 | { | ||
2399 | "name": "Bernhard Schussek", | ||
2400 | "email": "bschussek@gmail.com" | ||
2401 | } | ||
2402 | ], | ||
2403 | "description": "Assertions to validate method input/output with nice error messages.", | ||
2404 | "keywords": [ | ||
2405 | "assert", | ||
2406 | "check", | ||
2407 | "validate" | ||
2408 | ], | ||
2409 | "time": "2016-11-23T20:04:58+00:00" | ||
2410 | } | ||
2411 | ], | ||
2412 | "aliases": [], | ||
2413 | "minimum-stability": "stable", | ||
2414 | "stability-flags": { | ||
2415 | "pubsubhubbub/publisher": 20, | ||
2416 | "phpmd/phpmd": 0 | ||
2417 | }, | ||
2418 | "prefer-stable": false, | ||
2419 | "prefer-lowest": false, | ||
2420 | "platform": { | ||
2421 | "php": ">=5.5" | ||
2422 | }, | ||
2423 | "platform-dev": [] | ||
2424 | } | ||
@@ -1,8 +1,6 @@ | |||
1 | <?php | 1 | <?php |
2 | /** | 2 | /** |
3 | * Shaarli v0.8.3 - Shaare your links... | 3 | * Shaarli - The personal, minimalist, super-fast, database free, bookmarking service. |
4 | * | ||
5 | * The personal, minimalist, super-fast, database free, bookmarking service. | ||
6 | * | 4 | * |
7 | * Friendly fork by the Shaarli community: | 5 | * Friendly fork by the Shaarli community: |
8 | * - https://github.com/shaarli/Shaarli | 6 | * - https://github.com/shaarli/Shaarli |
@@ -25,7 +23,6 @@ if (date_default_timezone_get() == '') { | |||
25 | /* | 23 | /* |
26 | * PHP configuration | 24 | * PHP configuration |
27 | */ | 25 | */ |
28 | define('shaarli_version', '0.8.2'); | ||
29 | 26 | ||
30 | // http://server.com/x/shaarli --> /shaarli/ | 27 | // http://server.com/x/shaarli --> /shaarli/ |
31 | define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0))); | 28 | define('WEB_PATH', substr($_SERVER['REQUEST_URI'], 0, 1+strrpos($_SERVER['REQUEST_URI'], '/', 0))); |
@@ -91,6 +88,8 @@ try { | |||
91 | exit; | 88 | exit; |
92 | } | 89 | } |
93 | 90 | ||
91 | define('shaarli_version', ApplicationUtils::getVersion(__DIR__ .'/'. ApplicationUtils::$VERSION_FILE)); | ||
92 | |||
94 | // Force cookie path (but do not change lifetime) | 93 | // Force cookie path (but do not change lifetime) |
95 | $cookie = session_get_cookie_params(); | 94 | $cookie = session_get_cookie_params(); |
96 | $cookiedir = ''; | 95 | $cookiedir = ''; |
@@ -434,7 +433,7 @@ if (isset($_POST['login'])) | |||
434 | // Optional redirect after login: | 433 | // Optional redirect after login: |
435 | if (isset($_GET['post'])) { | 434 | if (isset($_GET['post'])) { |
436 | $uri = '?post='. urlencode($_GET['post']); | 435 | $uri = '?post='. urlencode($_GET['post']); |
437 | foreach (array('description', 'source', 'title') as $param) { | 436 | foreach (array('description', 'source', 'title', 'tags') as $param) { |
438 | if (!empty($_GET[$param])) { | 437 | if (!empty($_GET[$param])) { |
439 | $uri .= '&'.$param.'='.urlencode($_GET[$param]); | 438 | $uri .= '&'.$param.'='.urlencode($_GET[$param]); |
440 | } | 439 | } |
@@ -463,7 +462,7 @@ if (isset($_POST['login'])) | |||
463 | $redir = '&username='. $_POST['login']; | 462 | $redir = '&username='. $_POST['login']; |
464 | if (isset($_GET['post'])) { | 463 | if (isset($_GET['post'])) { |
465 | $redir .= '&post=' . urlencode($_GET['post']); | 464 | $redir .= '&post=' . urlencode($_GET['post']); |
466 | foreach (array('description', 'source', 'title') as $param) { | 465 | foreach (array('description', 'source', 'title', 'tags') as $param) { |
467 | if (!empty($_GET[$param])) { | 466 | if (!empty($_GET[$param])) { |
468 | $redir .= '&' . $param . '=' . urlencode($_GET[$param]); | 467 | $redir .= '&' . $param . '=' . urlencode($_GET[$param]); |
469 | } | 468 | } |
@@ -475,34 +474,6 @@ if (isset($_POST['login'])) | |||
475 | } | 474 | } |
476 | 475 | ||
477 | // ------------------------------------------------------------------------------------------ | 476 | // ------------------------------------------------------------------------------------------ |
478 | // Misc utility functions: | ||
479 | |||
480 | // Convert post_max_size/upload_max_filesize (e.g. '16M') parameters to bytes. | ||
481 | function return_bytes($val) | ||
482 | { | ||
483 | $val = trim($val); $last=strtolower($val[strlen($val)-1]); | ||
484 | switch($last) | ||
485 | { | ||
486 | case 'g': $val *= 1024; | ||
487 | case 'm': $val *= 1024; | ||
488 | case 'k': $val *= 1024; | ||
489 | } | ||
490 | return $val; | ||
491 | } | ||
492 | |||
493 | // Try to determine max file size for uploads (POST). | ||
494 | // Returns an integer (in bytes) | ||
495 | function getMaxFileSize() | ||
496 | { | ||
497 | $size1 = return_bytes(ini_get('post_max_size')); | ||
498 | $size2 = return_bytes(ini_get('upload_max_filesize')); | ||
499 | // Return the smaller of two: | ||
500 | $maxsize = min($size1,$size2); | ||
501 | // FIXME: Then convert back to readable notations ? (e.g. 2M instead of 2000000) | ||
502 | return $maxsize; | ||
503 | } | ||
504 | |||
505 | // ------------------------------------------------------------------------------------------ | ||
506 | // Token management for XSRF protection | 477 | // Token management for XSRF protection |
507 | // Token should be used in any form which acts on data (create,update,delete,import...). | 478 | // Token should be used in any form which acts on data (create,update,delete,import...). |
508 | if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are attached to the session. | 479 | if (!isset($_SESSION['tokens'])) $_SESSION['tokens']=array(); // Token are attached to the session. |
@@ -697,9 +668,11 @@ function showDaily($pageBuilder, $LINKSDB, $conf, $pluginManager) | |||
697 | 668 | ||
698 | $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000'); | 669 | $dayDate = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $day.'_000000'); |
699 | $data = array( | 670 | $data = array( |
671 | 'pagetitle' => $conf->get('general.title') .' - '. format_date($dayDate, false), | ||
700 | 'linksToDisplay' => $linksToDisplay, | 672 | 'linksToDisplay' => $linksToDisplay, |
701 | 'cols' => $columns, | 673 | 'cols' => $columns, |
702 | 'day' => $dayDate->getTimestamp(), | 674 | 'day' => $dayDate->getTimestamp(), |
675 | 'dayDate' => $dayDate, | ||
703 | 'previousday' => $previousday, | 676 | 'previousday' => $previousday, |
704 | 'nextday' => $nextday, | 677 | 'nextday' => $nextday, |
705 | ); | 678 | ); |
@@ -1052,7 +1025,13 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1052 | // Show login screen, then redirect to ?post=... | 1025 | // Show login screen, then redirect to ?post=... |
1053 | if (isset($_GET['post'])) | 1026 | if (isset($_GET['post'])) |
1054 | { | 1027 | { |
1055 | header('Location: ?do=login&post='.urlencode($_GET['post']).(!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').(!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').(!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')); // Redirect to login page, then back to post link. | 1028 | header( // Redirect to login page, then back to post link. |
1029 | 'Location: ?do=login&post='.urlencode($_GET['post']). | ||
1030 | (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):''). | ||
1031 | (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):''). | ||
1032 | (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):''). | ||
1033 | (!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'') | ||
1034 | ); | ||
1056 | exit; | 1035 | exit; |
1057 | } | 1036 | } |
1058 | 1037 | ||
@@ -1149,7 +1128,7 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1149 | $conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks'])); | 1128 | $conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks'])); |
1150 | $conf->set('updates.check_updates', !empty($_POST['updateCheck'])); | 1129 | $conf->set('updates.check_updates', !empty($_POST['updateCheck'])); |
1151 | $conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks'])); | 1130 | $conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks'])); |
1152 | $conf->set('api.enabled', !empty($_POST['apiEnabled'])); | 1131 | $conf->set('api.enabled', !empty($_POST['enableApi'])); |
1153 | $conf->set('api.secret', escape($_POST['apiSecret'])); | 1132 | $conf->set('api.secret', escape($_POST['apiSecret'])); |
1154 | try { | 1133 | try { |
1155 | $conf->write(isLoggedIn()); | 1134 | $conf->write(isLoggedIn()); |
@@ -1175,9 +1154,12 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1175 | $PAGE->assign('theme', $conf->get('resource.theme')); | 1154 | $PAGE->assign('theme', $conf->get('resource.theme')); |
1176 | $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl'))); | 1155 | $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl'))); |
1177 | $PAGE->assign('redirector', $conf->get('redirector.url')); | 1156 | $PAGE->assign('redirector', $conf->get('redirector.url')); |
1178 | list($timezone_form, $timezone_js) = generateTimeZoneForm($conf->get('general.timezone')); | 1157 | list($continents, $cities) = generateTimeZoneData( |
1179 | $PAGE->assign('timezone_form', $timezone_form); | 1158 | timezone_identifiers_list(), |
1180 | $PAGE->assign('timezone_js',$timezone_js); | 1159 | $conf->get('general.timezone') |
1160 | ); | ||
1161 | $PAGE->assign('continents', $continents); | ||
1162 | $PAGE->assign('cities', $cities); | ||
1181 | $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false)); | 1163 | $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false)); |
1182 | $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false)); | 1164 | $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false)); |
1183 | $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false)); | 1165 | $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false)); |
@@ -1257,7 +1239,7 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1257 | } | 1239 | } |
1258 | 1240 | ||
1259 | // lf_id should only be present if the link exists. | 1241 | // lf_id should only be present if the link exists. |
1260 | $id = !empty($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId(); | 1242 | $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId(); |
1261 | // Linkdate is kept here to: | 1243 | // Linkdate is kept here to: |
1262 | // - use the same permalink for notes as they're displayed when creating them | 1244 | // - use the same permalink for notes as they're displayed when creating them |
1263 | // - let users hack creation date of their posts | 1245 | // - let users hack creation date of their posts |
@@ -1337,9 +1319,13 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1337 | // -------- User clicked the "Cancel" button when editing a link. | 1319 | // -------- User clicked the "Cancel" button when editing a link. |
1338 | if (isset($_POST['cancel_edit'])) | 1320 | if (isset($_POST['cancel_edit'])) |
1339 | { | 1321 | { |
1322 | $id = isset($_POST['lf_id']) ? (int) escape($_POST['lf_id']) : false; | ||
1323 | if (! isset($LINKSDB[$id])) { | ||
1324 | header('Location: ?'); | ||
1325 | } | ||
1340 | // If we are called from the bookmarklet, we must close the popup: | 1326 | // If we are called from the bookmarklet, we must close the popup: |
1341 | if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } | 1327 | if (isset($_GET['source']) && ($_GET['source']=='bookmarklet' || $_GET['source']=='firefoxsocialapi')) { echo '<script>self.close();</script>'; exit; } |
1342 | $link = $LINKSDB[(int) escape($_POST['lf_id'])]; | 1328 | $link = $LINKSDB[$id]; |
1343 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); | 1329 | $returnurl = ( isset($_POST['returnurl']) ? $_POST['returnurl'] : '?' ); |
1344 | // Scroll to the link which has been edited. | 1330 | // Scroll to the link which has been edited. |
1345 | $returnurl .= '#'. $link['shorturl']; | 1331 | $returnurl .= '#'. $link['shorturl']; |
@@ -1525,7 +1511,22 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1525 | 1511 | ||
1526 | if (! isset($_POST['token']) || ! isset($_FILES['filetoupload'])) { | 1512 | if (! isset($_POST['token']) || ! isset($_FILES['filetoupload'])) { |
1527 | // Show import dialog | 1513 | // Show import dialog |
1528 | $PAGE->assign('maxfilesize', getMaxFileSize()); | 1514 | $PAGE->assign( |
1515 | 'maxfilesize', | ||
1516 | get_max_upload_size( | ||
1517 | ini_get('post_max_size'), | ||
1518 | ini_get('upload_max_filesize'), | ||
1519 | false | ||
1520 | ) | ||
1521 | ); | ||
1522 | $PAGE->assign( | ||
1523 | 'maxfilesizeHuman', | ||
1524 | get_max_upload_size( | ||
1525 | ini_get('post_max_size'), | ||
1526 | ini_get('upload_max_filesize'), | ||
1527 | true | ||
1528 | ) | ||
1529 | ); | ||
1529 | $PAGE->renderPage('import'); | 1530 | $PAGE->renderPage('import'); |
1530 | exit; | 1531 | exit; |
1531 | } | 1532 | } |
@@ -1535,7 +1536,7 @@ function renderPage($conf, $pluginManager, $LINKSDB) | |||
1535 | // The file is too big or some form field may be missing. | 1536 | // The file is too big or some form field may be missing. |
1536 | echo '<script>alert("The file you are trying to upload is probably' | 1537 | echo '<script>alert("The file you are trying to upload is probably' |
1537 | .' bigger than what this webserver can accept (' | 1538 | .' bigger than what this webserver can accept (' |
1538 | .getMaxFileSize().' bytes).' | 1539 | .get_max_upload_size(ini_get('post_max_size'), ini_get('upload_max_filesize')).').' |
1539 | .' Please upload in smaller chunks.");document.location=\'?do=' | 1540 | .' Please upload in smaller chunks.");document.location=\'?do=' |
1540 | .Router::$PAGE_IMPORT .'\';</script>'; | 1541 | .Router::$PAGE_IMPORT .'\';</script>'; |
1541 | exit; | 1542 | exit; |
@@ -1992,16 +1993,10 @@ function install($conf) | |||
1992 | exit; | 1993 | exit; |
1993 | } | 1994 | } |
1994 | 1995 | ||
1995 | // Display config form: | ||
1996 | list($timezone_form, $timezone_js) = generateTimeZoneForm(); | ||
1997 | $timezone_html = ''; | ||
1998 | if ($timezone_form != '') { | ||
1999 | $timezone_html = '<tr><td><b>Timezone:</b></td><td>'.$timezone_form.'</td></tr>'; | ||
2000 | } | ||
2001 | |||
2002 | $PAGE = new PageBuilder($conf); | 1996 | $PAGE = new PageBuilder($conf); |
2003 | $PAGE->assign('timezone_html',$timezone_html); | 1997 | list($continents, $cities) = generateTimeZoneData(timezone_identifiers_list(), date_default_timezone_get()); |
2004 | $PAGE->assign('timezone_js',$timezone_js); | 1998 | $PAGE->assign('continents', $continents); |
1999 | $PAGE->assign('cities', $cities); | ||
2005 | $PAGE->renderPage('install'); | 2000 | $PAGE->renderPage('install'); |
2006 | exit; | 2001 | exit; |
2007 | } | 2002 | } |
@@ -2252,9 +2247,10 @@ $app = new \Slim\App($container); | |||
2252 | 2247 | ||
2253 | // REST API routes | 2248 | // REST API routes |
2254 | $app->group('/api/v1', function() { | 2249 | $app->group('/api/v1', function() { |
2255 | $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo'); | 2250 | $this->get('/info', '\Shaarli\Api\Controllers\Info:getInfo')->setName('getInfo'); |
2256 | $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks'); | 2251 | $this->get('/links', '\Shaarli\Api\Controllers\Links:getLinks')->setName('getLinks'); |
2257 | $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink'); | 2252 | $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); |
2253 | $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); | ||
2258 | })->add('\Shaarli\Api\ApiMiddleware'); | 2254 | })->add('\Shaarli\Api\ApiMiddleware'); |
2259 | 2255 | ||
2260 | $response = $app->run(true); | 2256 | $response = $app->run(true); |
diff --git a/plugins/readityourself/book-open.png b/plugins/readityourself/book-open.png deleted file mode 100644 index 36513d7b..00000000 --- a/plugins/readityourself/book-open.png +++ /dev/null | |||
Binary files differ | |||
diff --git a/plugins/readityourself/readityourself.html b/plugins/readityourself/readityourself.html deleted file mode 100644 index 5e200715..00000000 --- a/plugins/readityourself/readityourself.html +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | <span><a href="%s?url=%s"><img class="linklist-plugin-icon" src="%s/readityourself/book-open.png" title="Read with Readityourself" alt="readityourself" /></a></span> | ||
diff --git a/plugins/readityourself/readityourself.meta b/plugins/readityourself/readityourself.meta deleted file mode 100644 index bd611dd0..00000000 --- a/plugins/readityourself/readityourself.meta +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | description="For each link, add a ReadItYourself icon to save the shaared URL." | ||
2 | parameters=READITYOUSELF_URL; \ No newline at end of file | ||
diff --git a/plugins/readityourself/readityourself.php b/plugins/readityourself/readityourself.php deleted file mode 100644 index 961c5bda..00000000 --- a/plugins/readityourself/readityourself.php +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | <?php | ||
2 | |||
3 | /** | ||
4 | * Plugin readityourself | ||
5 | */ | ||
6 | |||
7 | // If we're talking about https://github.com/memiks/readityourself | ||
8 | // it seems kinda dead. | ||
9 | // Not tested. | ||
10 | |||
11 | /** | ||
12 | * Init function, return an error if the server is not set. | ||
13 | * | ||
14 | * @param $conf ConfigManager instance. | ||
15 | * | ||
16 | * @return array Eventual error. | ||
17 | */ | ||
18 | function readityourself_init($conf) | ||
19 | { | ||
20 | $riyUrl = $conf->get('plugins.READITYOUSELF_URL'); | ||
21 | if (empty($riyUrl)) { | ||
22 | $error = 'Readityourself plugin error: '. | ||
23 | 'Please define the "READITYOUSELF_URL" setting in the plugin administration page.'; | ||
24 | return array($error); | ||
25 | } | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * Add readityourself icon to link_plugin when rendering linklist. | ||
30 | * | ||
31 | * @param mixed $data Linklist data. | ||
32 | * @param ConfigManager $conf Configuration Manager instance. | ||
33 | * | ||
34 | * @return mixed - linklist data with readityourself plugin. | ||
35 | */ | ||
36 | function hook_readityourself_render_linklist($data, $conf) | ||
37 | { | ||
38 | $riyUrl = $conf->get('plugins.READITYOUSELF_URL'); | ||
39 | if (empty($riyUrl)) { | ||
40 | return $data; | ||
41 | } | ||
42 | |||
43 | $readityourself_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/readityourself/readityourself.html'); | ||
44 | |||
45 | foreach ($data['links'] as &$value) { | ||
46 | $readityourself = sprintf($readityourself_html, $riyUrl, $value['url'], PluginManager::$PLUGINS_PATH); | ||
47 | $value['link_plugin'][] = $readityourself; | ||
48 | } | ||
49 | |||
50 | return $data; | ||
51 | } | ||
diff --git a/shaarli_version.php b/shaarli_version.php index 3f79a4c6..9167b43e 100644 --- a/shaarli_version.php +++ b/shaarli_version.php | |||
@@ -1 +1 @@ | |||
<?php /* 0.8.3 */ ?> | <?php /* dev */ ?> | ||
diff --git a/tests/ApplicationUtilsTest.php b/tests/ApplicationUtilsTest.php index ad86e21c..ff4c9e17 100644 --- a/tests/ApplicationUtilsTest.php +++ b/tests/ApplicationUtilsTest.php | |||
@@ -17,7 +17,7 @@ class FakeApplicationUtils extends ApplicationUtils | |||
17 | /** | 17 | /** |
18 | * Toggle HTTP requests, allow overriding the version code | 18 | * Toggle HTTP requests, allow overriding the version code |
19 | */ | 19 | */ |
20 | public static function getLatestGitVersionCode($url, $timeout=0) | 20 | public static function getVersion($url, $timeout=0) |
21 | { | 21 | { |
22 | return self::$VERSION_CODE; | 22 | return self::$VERSION_CODE; |
23 | } | 23 | } |
@@ -45,17 +45,27 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * Remove test version file if it exists | ||
49 | */ | ||
50 | public function tearDown() | ||
51 | { | ||
52 | if (is_file('sandbox/version.php')) { | ||
53 | unlink('sandbox/version.php'); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | /** | ||
48 | * Retrieve the latest version code available on Git | 58 | * Retrieve the latest version code available on Git |
49 | * | 59 | * |
50 | * Expected format: Semantic Versioning - major.minor.patch | 60 | * Expected format: Semantic Versioning - major.minor.patch |
51 | */ | 61 | */ |
52 | public function testGetLatestGitVersionCode() | 62 | public function testGetVersionCode() |
53 | { | 63 | { |
54 | $testTimeout = 10; | 64 | $testTimeout = 10; |
55 | 65 | ||
56 | $this->assertEquals( | 66 | $this->assertEquals( |
57 | '0.5.4', | 67 | '0.5.4', |
58 | ApplicationUtils::getLatestGitVersionCode( | 68 | ApplicationUtils::getVersion( |
59 | 'https://raw.githubusercontent.com/shaarli/Shaarli/' | 69 | 'https://raw.githubusercontent.com/shaarli/Shaarli/' |
60 | .'v0.5.4/shaarli_version.php', | 70 | .'v0.5.4/shaarli_version.php', |
61 | $testTimeout | 71 | $testTimeout |
@@ -63,23 +73,35 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase | |||
63 | ); | 73 | ); |
64 | $this->assertRegExp( | 74 | $this->assertRegExp( |
65 | self::$versionPattern, | 75 | self::$versionPattern, |
66 | ApplicationUtils::getLatestGitVersionCode( | 76 | ApplicationUtils::getVersion( |
67 | 'https://raw.githubusercontent.com/shaarli/Shaarli/' | 77 | 'https://raw.githubusercontent.com/shaarli/Shaarli/' |
68 | .'master/shaarli_version.php', | 78 | .'latest/shaarli_version.php', |
69 | $testTimeout | 79 | $testTimeout |
70 | ) | 80 | ) |
71 | ); | 81 | ); |
72 | } | 82 | } |
73 | 83 | ||
74 | /** | 84 | /** |
75 | * Attempt to retrieve the latest version from an invalid URL | 85 | * Attempt to retrieve the latest version from an invalid File |
86 | */ | ||
87 | public function testGetVersionCodeFromFile() | ||
88 | { | ||
89 | file_put_contents('sandbox/version.php', '<?php /* 1.2.3 */ ?>'. PHP_EOL); | ||
90 | $this->assertEquals( | ||
91 | '1.2.3', | ||
92 | ApplicationUtils::getVersion('sandbox/version.php', 1) | ||
93 | ); | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Attempt to retrieve the latest version from an invalid File | ||
76 | */ | 98 | */ |
77 | public function testGetLatestGitVersionCodeInvalidUrl() | 99 | public function testGetVersionCodeInvalidFile() |
78 | { | 100 | { |
79 | $oldlog = ini_get('error_log'); | 101 | $oldlog = ini_get('error_log'); |
80 | ini_set('error_log', '/dev/null'); | 102 | ini_set('error_log', '/dev/null'); |
81 | $this->assertFalse( | 103 | $this->assertFalse( |
82 | ApplicationUtils::getLatestGitVersionCode('htttp://null.io', 1) | 104 | ApplicationUtils::getVersion('idontexist', 1) |
83 | ); | 105 | ); |
84 | ini_set('error_log', $oldlog); | 106 | ini_set('error_log', $oldlog); |
85 | } | 107 | } |
@@ -332,4 +354,15 @@ class ApplicationUtilsTest extends PHPUnit_Framework_TestCase | |||
332 | ApplicationUtils::checkResourcePermissions($conf) | 354 | ApplicationUtils::checkResourcePermissions($conf) |
333 | ); | 355 | ); |
334 | } | 356 | } |
357 | |||
358 | /** | ||
359 | * Check update with 'dev' as curent version (master branch). | ||
360 | * It should always return false. | ||
361 | */ | ||
362 | public function testCheckUpdateDev() | ||
363 | { | ||
364 | $this->assertFalse( | ||
365 | ApplicationUtils::checkUpdate('dev', self::$testUpdateFile, 100, true, true) | ||
366 | ); | ||
367 | } | ||
335 | } | 368 | } |
diff --git a/tests/TimeZoneTest.php b/tests/TimeZoneTest.php index 2976d116..127fdc19 100644 --- a/tests/TimeZoneTest.php +++ b/tests/TimeZoneTest.php | |||
@@ -11,24 +11,45 @@ require_once 'application/TimeZone.php'; | |||
11 | class TimeZoneTest extends PHPUnit_Framework_TestCase | 11 | class TimeZoneTest extends PHPUnit_Framework_TestCase |
12 | { | 12 | { |
13 | /** | 13 | /** |
14 | * @var array of timezones | ||
15 | */ | ||
16 | protected $installedTimezones; | ||
17 | |||
18 | public function setUp() | ||
19 | { | ||
20 | $this->installedTimezones = [ | ||
21 | 'Antarctica/Syowa', | ||
22 | 'Europe/London', | ||
23 | 'Europe/Paris', | ||
24 | 'UTC' | ||
25 | ]; | ||
26 | } | ||
27 | |||
28 | /** | ||
14 | * Generate a timezone selection form | 29 | * Generate a timezone selection form |
15 | */ | 30 | */ |
16 | public function testGenerateTimeZoneForm() | 31 | public function testGenerateTimeZoneForm() |
17 | { | 32 | { |
18 | $generated = generateTimeZoneForm(); | 33 | $expected = [ |
34 | 'continents' => [ | ||
35 | 'Antarctica', | ||
36 | 'Europe', | ||
37 | 'UTC', | ||
38 | 'selected' => '', | ||
39 | ], | ||
40 | 'cities' => [ | ||
41 | ['continent' => 'Antarctica', 'city' => 'Syowa'], | ||
42 | ['continent' => 'Europe', 'city' => 'London'], | ||
43 | ['continent' => 'Europe', 'city' => 'Paris'], | ||
44 | ['continent' => 'UTC', 'city' => 'UTC'], | ||
45 | 'selected' => '', | ||
46 | ] | ||
47 | ]; | ||
19 | 48 | ||
20 | // HTML form | 49 | list($continents, $cities) = generateTimeZoneData($this->installedTimezones); |
21 | $this->assertStringStartsWith('Continent:<select', $generated[0]); | ||
22 | $this->assertContains('selected="selected"', $generated[0]); | ||
23 | $this->assertStringEndsWith('</select><br />', $generated[0]); | ||
24 | 50 | ||
25 | // Javascript handler | 51 | $this->assertEquals($expected['continents'], $continents); |
26 | $this->assertStringStartsWith('<script>', $generated[1]); | 52 | $this->assertEquals($expected['cities'], $cities); |
27 | $this->assertContains( | ||
28 | '<option value=\"Bermuda\">Bermuda<\/option>', | ||
29 | $generated[1] | ||
30 | ); | ||
31 | $this->assertStringEndsWith('</script>', $generated[1]); | ||
32 | } | 53 | } |
33 | 54 | ||
34 | /** | 55 | /** |
@@ -36,28 +57,26 @@ class TimeZoneTest extends PHPUnit_Framework_TestCase | |||
36 | */ | 57 | */ |
37 | public function testGenerateTimeZoneFormPreselected() | 58 | public function testGenerateTimeZoneFormPreselected() |
38 | { | 59 | { |
39 | $generated = generateTimeZoneForm('Antarctica/Syowa'); | 60 | $expected = [ |
40 | 61 | 'continents' => [ | |
41 | // HTML form | 62 | 'Antarctica', |
42 | $this->assertStringStartsWith('Continent:<select', $generated[0]); | 63 | 'Europe', |
43 | $this->assertContains( | 64 | 'UTC', |
44 | 'value="Antarctica" selected="selected"', | 65 | 'selected' => 'Antarctica', |
45 | $generated[0] | 66 | ], |
46 | ); | 67 | 'cities' => [ |
47 | $this->assertContains( | 68 | ['continent' => 'Antarctica', 'city' => 'Syowa'], |
48 | 'value="Syowa" selected="selected"', | 69 | ['continent' => 'Europe', 'city' => 'London'], |
49 | $generated[0] | 70 | ['continent' => 'Europe', 'city' => 'Paris'], |
50 | ); | 71 | ['continent' => 'UTC', 'city' => 'UTC'], |
51 | $this->assertStringEndsWith('</select><br />', $generated[0]); | 72 | 'selected' => 'Syowa', |
73 | ] | ||
74 | ]; | ||
52 | 75 | ||
76 | list($continents, $cities) = generateTimeZoneData($this->installedTimezones, 'Antarctica/Syowa'); | ||
53 | 77 | ||
54 | // Javascript handler | 78 | $this->assertEquals($expected['continents'], $continents); |
55 | $this->assertStringStartsWith('<script>', $generated[1]); | 79 | $this->assertEquals($expected['cities'], $cities); |
56 | $this->assertContains( | ||
57 | '<option value=\"Bermuda\">Bermuda<\/option>', | ||
58 | $generated[1] | ||
59 | ); | ||
60 | $this->assertStringEndsWith('</script>', $generated[1]); | ||
61 | } | 80 | } |
62 | 81 | ||
63 | /** | 82 | /** |
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index e70cc1ae..d6a0aad5 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php | |||
@@ -4,6 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | require_once 'application/Utils.php'; | 6 | require_once 'application/Utils.php'; |
7 | require_once 'application/Languages.php'; | ||
7 | require_once 'tests/utils/ReferenceSessionIdHashes.php'; | 8 | require_once 'tests/utils/ReferenceSessionIdHashes.php'; |
8 | 9 | ||
9 | // Initialize reference data before PHPUnit starts a session | 10 | // Initialize reference data before PHPUnit starts a session |
@@ -326,4 +327,94 @@ class UtilsTest extends PHPUnit_Framework_TestCase | |||
326 | $this->assertFalse(format_date([])); | 327 | $this->assertFalse(format_date([])); |
327 | $this->assertFalse(format_date(null)); | 328 | $this->assertFalse(format_date(null)); |
328 | } | 329 | } |
330 | |||
331 | /** | ||
332 | * Test is_integer_mixed with valid values | ||
333 | */ | ||
334 | public function testIsIntegerMixedValid() | ||
335 | { | ||
336 | $this->assertTrue(is_integer_mixed(12)); | ||
337 | $this->assertTrue(is_integer_mixed('12')); | ||
338 | $this->assertTrue(is_integer_mixed(-12)); | ||
339 | $this->assertTrue(is_integer_mixed('-12')); | ||
340 | $this->assertTrue(is_integer_mixed(0)); | ||
341 | $this->assertTrue(is_integer_mixed('0')); | ||
342 | $this->assertTrue(is_integer_mixed(0x0a)); | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * Test is_integer_mixed with invalid values | ||
347 | */ | ||
348 | public function testIsIntegerMixedInvalid() | ||
349 | { | ||
350 | $this->assertFalse(is_integer_mixed(true)); | ||
351 | $this->assertFalse(is_integer_mixed(false)); | ||
352 | $this->assertFalse(is_integer_mixed([])); | ||
353 | $this->assertFalse(is_integer_mixed(['test'])); | ||
354 | $this->assertFalse(is_integer_mixed([12])); | ||
355 | $this->assertFalse(is_integer_mixed(new DateTime())); | ||
356 | $this->assertFalse(is_integer_mixed('0x0a')); | ||
357 | $this->assertFalse(is_integer_mixed('12k')); | ||
358 | $this->assertFalse(is_integer_mixed('k12')); | ||
359 | $this->assertFalse(is_integer_mixed('')); | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * Test return_bytes | ||
364 | */ | ||
365 | public function testReturnBytes() | ||
366 | { | ||
367 | $this->assertEquals(2 * 1024, return_bytes('2k')); | ||
368 | $this->assertEquals(2 * 1024, return_bytes('2K')); | ||
369 | $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2m')); | ||
370 | $this->assertEquals(2 * (pow(1024, 2)), return_bytes('2M')); | ||
371 | $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2g')); | ||
372 | $this->assertEquals(2 * (pow(1024, 3)), return_bytes('2G')); | ||
373 | $this->assertEquals(374, return_bytes('374')); | ||
374 | $this->assertEquals(374, return_bytes(374)); | ||
375 | $this->assertEquals(0, return_bytes('0')); | ||
376 | $this->assertEquals(0, return_bytes(0)); | ||
377 | $this->assertEquals(-1, return_bytes('-1')); | ||
378 | $this->assertEquals(-1, return_bytes(-1)); | ||
379 | $this->assertEquals('', return_bytes('')); | ||
380 | } | ||
381 | |||
382 | /** | ||
383 | * Test human_bytes | ||
384 | */ | ||
385 | public function testHumanBytes() | ||
386 | { | ||
387 | $this->assertEquals('2kiB', human_bytes(2 * 1024)); | ||
388 | $this->assertEquals('2kiB', human_bytes(strval(2 * 1024))); | ||
389 | $this->assertEquals('2MiB', human_bytes(2 * (pow(1024, 2)))); | ||
390 | $this->assertEquals('2MiB', human_bytes(strval(2 * (pow(1024, 2))))); | ||
391 | $this->assertEquals('2GiB', human_bytes(2 * (pow(1024, 3)))); | ||
392 | $this->assertEquals('2GiB', human_bytes(strval(2 * (pow(1024, 3))))); | ||
393 | $this->assertEquals('374B', human_bytes(374)); | ||
394 | $this->assertEquals('374B', human_bytes('374')); | ||
395 | $this->assertEquals('232kiB', human_bytes(237481)); | ||
396 | $this->assertEquals('Unlimited', human_bytes('0')); | ||
397 | $this->assertEquals('Unlimited', human_bytes(0)); | ||
398 | $this->assertEquals('Setting not set', human_bytes('')); | ||
399 | } | ||
400 | |||
401 | /** | ||
402 | * Test get_max_upload_size with formatting | ||
403 | */ | ||
404 | public function testGetMaxUploadSize() | ||
405 | { | ||
406 | $this->assertEquals('1MiB', get_max_upload_size(2097152, '1024k')); | ||
407 | $this->assertEquals('1MiB', get_max_upload_size('1m', '2m')); | ||
408 | $this->assertEquals('100B', get_max_upload_size(100, 100)); | ||
409 | } | ||
410 | |||
411 | /** | ||
412 | * Test get_max_upload_size without formatting | ||
413 | */ | ||
414 | public function testGetMaxUploadSizeRaw() | ||
415 | { | ||
416 | $this->assertEquals('1048576', get_max_upload_size(2097152, '1024k', false)); | ||
417 | $this->assertEquals('1048576', get_max_upload_size('1m', '2m', false)); | ||
418 | $this->assertEquals('100', get_max_upload_size(100, 100, false)); | ||
419 | } | ||
329 | } | 420 | } |
diff --git a/tests/api/controllers/PostLinkTest.php b/tests/api/controllers/PostLinkTest.php new file mode 100644 index 00000000..3ed7bcb0 --- /dev/null +++ b/tests/api/controllers/PostLinkTest.php | |||
@@ -0,0 +1,193 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Shaarli\Api\Controllers; | ||
4 | |||
5 | |||
6 | use Shaarli\Config\ConfigManager; | ||
7 | use Slim\Container; | ||
8 | use Slim\Http\Environment; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | |||
12 | /** | ||
13 | * Class PostLinkTest | ||
14 | * | ||
15 | * Test POST Link REST API service. | ||
16 | * | ||
17 | * @package Shaarli\Api\Controllers | ||
18 | */ | ||
19 | class PostLinkTest extends \PHPUnit_Framework_TestCase | ||
20 | { | ||
21 | /** | ||
22 | * @var string datastore to test write operations | ||
23 | */ | ||
24 | protected static $testDatastore = 'sandbox/datastore.php'; | ||
25 | |||
26 | /** | ||
27 | * @var ConfigManager instance | ||
28 | */ | ||
29 | protected $conf; | ||
30 | |||
31 | /** | ||
32 | * @var \ReferenceLinkDB instance. | ||
33 | */ | ||
34 | protected $refDB = null; | ||
35 | |||
36 | /** | ||
37 | * @var Container instance. | ||
38 | */ | ||
39 | protected $container; | ||
40 | |||
41 | /** | ||
42 | * @var Links controller instance. | ||
43 | */ | ||
44 | protected $controller; | ||
45 | |||
46 | /** | ||
47 | * Number of JSON field per link. | ||
48 | */ | ||
49 | const NB_FIELDS_LINK = 9; | ||
50 | |||
51 | /** | ||
52 | * Before every test, instantiate a new Api with its config, plugins and links. | ||
53 | */ | ||
54 | public function setUp() | ||
55 | { | ||
56 | $this->conf = new ConfigManager('tests/utils/config/configJson.json.php'); | ||
57 | $this->refDB = new \ReferenceLinkDB(); | ||
58 | $this->refDB->write(self::$testDatastore); | ||
59 | |||
60 | $this->container = new Container(); | ||
61 | $this->container['conf'] = $this->conf; | ||
62 | $this->container['db'] = new \LinkDB(self::$testDatastore, true, false); | ||
63 | |||
64 | $this->controller = new Links($this->container); | ||
65 | |||
66 | $mock = $this->getMock('\Slim\Router', ['relativePathFor']); | ||
67 | $mock->expects($this->any()) | ||
68 | ->method('relativePathFor') | ||
69 | ->willReturn('api/v1/links/1'); | ||
70 | |||
71 | // affect @property-read... seems to work | ||
72 | $this->controller->getCi()->router = $mock; | ||
73 | |||
74 | // Used by index_url(). | ||
75 | $this->controller->getCi()['environment'] = [ | ||
76 | 'SERVER_NAME' => 'domain.tld', | ||
77 | 'SERVER_PORT' => 80, | ||
78 | 'SCRIPT_NAME' => '/', | ||
79 | ]; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * After every test, remove the test datastore. | ||
84 | */ | ||
85 | public function tearDown() | ||
86 | { | ||
87 | @unlink(self::$testDatastore); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * Test link creation without any field: creates a blank note. | ||
92 | */ | ||
93 | public function testPostLinkMinimal() | ||
94 | { | ||
95 | $env = Environment::mock([ | ||
96 | 'REQUEST_METHOD' => 'POST', | ||
97 | ]); | ||
98 | |||
99 | $request = Request::createFromEnvironment($env); | ||
100 | |||
101 | $response = $this->controller->postLink($request, new Response()); | ||
102 | $this->assertEquals(201, $response->getStatusCode()); | ||
103 | $this->assertEquals('api/v1/links/1', $response->getHeader('Location')[0]); | ||
104 | $data = json_decode((string) $response->getBody(), true); | ||
105 | $this->assertEquals(self::NB_FIELDS_LINK, count($data)); | ||
106 | $this->assertEquals(43, $data['id']); | ||
107 | $this->assertRegExp('/[\w-_]{6}/', $data['shorturl']); | ||
108 | $this->assertEquals('http://domain.tld/?' . $data['shorturl'], $data['url']); | ||
109 | $this->assertEquals('?' . $data['shorturl'], $data['title']); | ||
110 | $this->assertEquals('', $data['description']); | ||
111 | $this->assertEquals([], $data['tags']); | ||
112 | $this->assertEquals(false, $data['private']); | ||
113 | $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])); | ||
114 | $this->assertEquals('', $data['updated']); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * Test link creation with all available fields. | ||
119 | */ | ||
120 | public function testPostLinkFull() | ||
121 | { | ||
122 | $link = [ | ||
123 | 'url' => 'website.tld/test?foo=bar', | ||
124 | 'title' => 'new entry', | ||
125 | 'description' => 'shaare description', | ||
126 | 'tags' => ['one', 'two'], | ||
127 | 'private' => true, | ||
128 | ]; | ||
129 | $env = Environment::mock([ | ||
130 | 'REQUEST_METHOD' => 'POST', | ||
131 | 'CONTENT_TYPE' => 'application/json' | ||
132 | ]); | ||
133 | |||
134 | $request = Request::createFromEnvironment($env); | ||
135 | $request = $request->withParsedBody($link); | ||
136 | $response = $this->controller->postLink($request, new Response()); | ||
137 | |||
138 | $this->assertEquals(201, $response->getStatusCode()); | ||
139 | $this->assertEquals('api/v1/links/1', $response->getHeader('Location')[0]); | ||
140 | $data = json_decode((string) $response->getBody(), true); | ||
141 | $this->assertEquals(self::NB_FIELDS_LINK, count($data)); | ||
142 | $this->assertEquals(43, $data['id']); | ||
143 | $this->assertRegExp('/[\w-_]{6}/', $data['shorturl']); | ||
144 | $this->assertEquals('http://' . $link['url'], $data['url']); | ||
145 | $this->assertEquals($link['title'], $data['title']); | ||
146 | $this->assertEquals($link['description'], $data['description']); | ||
147 | $this->assertEquals($link['tags'], $data['tags']); | ||
148 | $this->assertEquals(true, $data['private']); | ||
149 | $this->assertTrue(new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])); | ||
150 | $this->assertEquals('', $data['updated']); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Test link creation with an existing link (duplicate URL). Should return a 409 HTTP error and the existing link. | ||
155 | */ | ||
156 | public function testPostLinkDuplicate() | ||
157 | { | ||
158 | $link = [ | ||
159 | 'url' => 'mediagoblin.org/', | ||
160 | 'title' => 'new entry', | ||
161 | 'description' => 'shaare description', | ||
162 | 'tags' => ['one', 'two'], | ||
163 | 'private' => true, | ||
164 | ]; | ||
165 | $env = Environment::mock([ | ||
166 | 'REQUEST_METHOD' => 'POST', | ||
167 | 'CONTENT_TYPE' => 'application/json' | ||
168 | ]); | ||
169 | |||
170 | $request = Request::createFromEnvironment($env); | ||
171 | $request = $request->withParsedBody($link); | ||
172 | $response = $this->controller->postLink($request, new Response()); | ||
173 | |||
174 | $this->assertEquals(409, $response->getStatusCode()); | ||
175 | $data = json_decode((string) $response->getBody(), true); | ||
176 | $this->assertEquals(self::NB_FIELDS_LINK, count($data)); | ||
177 | $this->assertEquals(7, $data['id']); | ||
178 | $this->assertEquals('IuWvgA', $data['shorturl']); | ||
179 | $this->assertEquals('http://mediagoblin.org/', $data['url']); | ||
180 | $this->assertEquals('MediaGoblin', $data['title']); | ||
181 | $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']); | ||
182 | $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']); | ||
183 | $this->assertEquals(false, $data['private']); | ||
184 | $this->assertEquals( | ||
185 | \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130614_184135'), | ||
186 | \DateTime::createFromFormat(\DateTime::ATOM, $data['created']) | ||
187 | ); | ||
188 | $this->assertEquals( | ||
189 | \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130615_184230'), | ||
190 | \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']) | ||
191 | ); | ||
192 | } | ||
193 | } | ||
diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php index 545fa572..6c9c9adc 100644 --- a/tests/languages/de/UtilsDeTest.php +++ b/tests/languages/de/UtilsDeTest.php | |||
@@ -11,7 +11,16 @@ class UtilsDeTest extends UtilsTest | |||
11 | public function testDateFormat() | 11 | public function testDateFormat() |
12 | { | 12 | { |
13 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | 13 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); |
14 | $this->assertRegExp('/1. Januar 2017 (um )?10:11:12 GMT\+0?3(:00)?/', format_date($date, true)); | 14 | $this->assertRegExp('/1\. Januar 2017 (um )?10:11:12 GMT\+0?3(:00)?/', format_date($date, true, true)); |
15 | } | ||
16 | |||
17 | /** | ||
18 | * Test date_format() without time. | ||
19 | */ | ||
20 | public function testDateFormatNoTime() | ||
21 | { | ||
22 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | ||
23 | $this->assertRegExp('/1\. Januar 2017/', format_date($date, false,true)); | ||
15 | } | 24 | } |
16 | 25 | ||
17 | /** | 26 | /** |
@@ -20,7 +29,16 @@ class UtilsDeTest extends UtilsTest | |||
20 | public function testDateFormatDefault() | 29 | public function testDateFormatDefault() |
21 | { | 30 | { |
22 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | 31 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); |
23 | $this->assertEquals('So 01 Jan 2017 10:11:12 EAT', format_date($date, false)); | 32 | $this->assertEquals('So 01 Jan 2017 10:11:12 EAT', format_date($date, true, false)); |
33 | } | ||
34 | |||
35 | /** | ||
36 | * Test date_format() using builtin PHP function strftime without time. | ||
37 | */ | ||
38 | public function testDateFormatDefaultNoTime() | ||
39 | { | ||
40 | $date = DateTime::createFromFormat('Ymd_His', '20170201_101112'); | ||
41 | $this->assertEquals('01.02.2017', format_date($date, false, false)); | ||
24 | } | 42 | } |
25 | 43 | ||
26 | /** | 44 | /** |
diff --git a/tests/languages/en/UtilsEnTest.php b/tests/languages/en/UtilsEnTest.php index 7c829ac7..d8680b2b 100644 --- a/tests/languages/en/UtilsEnTest.php +++ b/tests/languages/en/UtilsEnTest.php | |||
@@ -11,7 +11,16 @@ class UtilsEnTest extends UtilsTest | |||
11 | public function testDateFormat() | 11 | public function testDateFormat() |
12 | { | 12 | { |
13 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | 13 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); |
14 | $this->assertRegExp('/January 1, 2017 (at )?10:11:12 AM GMT\+0?3(:00)?/', format_date($date, true)); | 14 | $this->assertRegExp('/January 1, 2017 (at )?10:11:12 AM GMT\+0?3(:00)?/', format_date($date, true, true)); |
15 | } | ||
16 | |||
17 | /** | ||
18 | * Test date_format() without time. | ||
19 | */ | ||
20 | public function testDateFormatNoTime() | ||
21 | { | ||
22 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | ||
23 | $this->assertRegExp('/January 1, 2017/', format_date($date, false, true)); | ||
15 | } | 24 | } |
16 | 25 | ||
17 | /** | 26 | /** |
@@ -20,7 +29,16 @@ class UtilsEnTest extends UtilsTest | |||
20 | public function testDateFormatDefault() | 29 | public function testDateFormatDefault() |
21 | { | 30 | { |
22 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | 31 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); |
23 | $this->assertEquals('Sun 01 Jan 2017 10:11:12 AM EAT', format_date($date, false)); | 32 | $this->assertEquals('Sun 01 Jan 2017 10:11:12 AM EAT', format_date($date, true, false)); |
33 | } | ||
34 | |||
35 | /** | ||
36 | * Test date_format() using builtin PHP function strftime without time. | ||
37 | */ | ||
38 | public function testDateFormatDefaultNoTime() | ||
39 | { | ||
40 | $date = DateTime::createFromFormat('Ymd_His', '20170201_101112'); | ||
41 | $this->assertEquals('02/01/2017', format_date($date, false, false)); | ||
24 | } | 42 | } |
25 | 43 | ||
26 | /** | 44 | /** |
diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php index 45996ee2..0d50a878 100644 --- a/tests/languages/fr/UtilsFrTest.php +++ b/tests/languages/fr/UtilsFrTest.php | |||
@@ -15,12 +15,30 @@ class UtilsFrTest extends UtilsTest | |||
15 | } | 15 | } |
16 | 16 | ||
17 | /** | 17 | /** |
18 | * Test date_format() without time. | ||
19 | */ | ||
20 | public function testDateFormatNoTime() | ||
21 | { | ||
22 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | ||
23 | $this->assertRegExp('/1 janvier 2017/', format_date($date, false, true)); | ||
24 | } | ||
25 | |||
26 | /** | ||
18 | * Test date_format() using builtin PHP function strftime. | 27 | * Test date_format() using builtin PHP function strftime. |
19 | */ | 28 | */ |
20 | public function testDateFormatDefault() | 29 | public function testDateFormatDefault() |
21 | { | 30 | { |
22 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); | 31 | $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); |
23 | $this->assertEquals('dim. 01 janv. 2017 10:11:12 EAT', format_date($date, false)); | 32 | $this->assertEquals('dim. 01 janv. 2017 10:11:12 EAT', format_date($date, true, false)); |
33 | } | ||
34 | |||
35 | /** | ||
36 | * Test date_format() using builtin PHP function strftime without time. | ||
37 | */ | ||
38 | public function testDateFormatDefaultNoTime() | ||
39 | { | ||
40 | $date = DateTime::createFromFormat('Ymd_His', '20170201_101112'); | ||
41 | $this->assertEquals('01/02/2017', format_date($date, false, false)); | ||
24 | } | 42 | } |
25 | 43 | ||
26 | /** | 44 | /** |
diff --git a/tests/plugins/PluginReadityourselfTest.php b/tests/plugins/PluginReadityourselfTest.php deleted file mode 100644 index bbba9676..00000000 --- a/tests/plugins/PluginReadityourselfTest.php +++ /dev/null | |||
@@ -1,99 +0,0 @@ | |||
1 | <?php | ||
2 | use Shaarli\Config\ConfigManager; | ||
3 | |||
4 | /** | ||
5 | * PluginReadityourselfTest.php.php | ||
6 | */ | ||
7 | |||
8 | require_once 'plugins/readityourself/readityourself.php'; | ||
9 | |||
10 | /** | ||
11 | * Class PluginWallabagTest | ||
12 | * Unit test for the Wallabag plugin | ||
13 | */ | ||
14 | class PluginReadityourselfTest extends PHPUnit_Framework_TestCase | ||
15 | { | ||
16 | /** | ||
17 | * Reset plugin path | ||
18 | */ | ||
19 | public function setUp() | ||
20 | { | ||
21 | PluginManager::$PLUGINS_PATH = 'plugins'; | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * Test Readityourself init without errors. | ||
26 | */ | ||
27 | public function testReadityourselfInitNoError() | ||
28 | { | ||
29 | $conf = new ConfigManager(''); | ||
30 | $conf->set('plugins.READITYOUSELF_URL', 'value'); | ||
31 | $errors = readityourself_init($conf); | ||
32 | $this->assertEmpty($errors); | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * Test Readityourself init with errors. | ||
37 | */ | ||
38 | public function testReadityourselfInitError() | ||
39 | { | ||
40 | $conf = new ConfigManager(''); | ||
41 | $errors = readityourself_init($conf); | ||
42 | $this->assertNotEmpty($errors); | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * Test render_linklist hook. | ||
47 | */ | ||
48 | public function testReadityourselfLinklist() | ||
49 | { | ||
50 | $conf = new ConfigManager(''); | ||
51 | $conf->set('plugins.READITYOUSELF_URL', 'value'); | ||
52 | $str = 'http://randomstr.com/test'; | ||
53 | $data = array( | ||
54 | 'title' => $str, | ||
55 | 'links' => array( | ||
56 | array( | ||
57 | 'url' => $str, | ||
58 | ) | ||
59 | ) | ||
60 | ); | ||
61 | |||
62 | $data = hook_readityourself_render_linklist($data, $conf); | ||
63 | $link = $data['links'][0]; | ||
64 | // data shouldn't be altered | ||
65 | $this->assertEquals($str, $data['title']); | ||
66 | $this->assertEquals($str, $link['url']); | ||
67 | |||
68 | // plugin data | ||
69 | $this->assertEquals(1, count($link['link_plugin'])); | ||
70 | $this->assertNotFalse(strpos($link['link_plugin'][0], $str)); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Test without config: nothing should happened. | ||
75 | */ | ||
76 | public function testReadityourselfLinklistWithoutConfig() | ||
77 | { | ||
78 | $conf = new ConfigManager(''); | ||
79 | $conf->set('plugins.READITYOUSELF_URL', null); | ||
80 | $str = 'http://randomstr.com/test'; | ||
81 | $data = array( | ||
82 | 'title' => $str, | ||
83 | 'links' => array( | ||
84 | array( | ||
85 | 'url' => $str, | ||
86 | ) | ||
87 | ) | ||
88 | ); | ||
89 | |||
90 | $data = hook_readityourself_render_linklist($data, $conf); | ||
91 | $link = $data['links'][0]; | ||
92 | // data shouldn't be altered | ||
93 | $this->assertEquals($str, $data['title']); | ||
94 | $this->assertEquals($str, $link['url']); | ||
95 | |||
96 | // plugin data | ||
97 | $this->assertArrayNotHasKey('link_plugin', $link); | ||
98 | } | ||
99 | } | ||
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php index 36d58c68..1f4b3063 100644 --- a/tests/utils/ReferenceLinkDB.php +++ b/tests/utils/ReferenceLinkDB.php | |||
@@ -56,7 +56,7 @@ class ReferenceLinkDB | |||
56 | 0, | 56 | 0, |
57 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130614_184135'), | 57 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130614_184135'), |
58 | 'gnu media web .hidden hashtag', | 58 | 'gnu media web .hidden hashtag', |
59 | null, | 59 | DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20130615_184230'), |
60 | 'IuWvgA' | 60 | 'IuWvgA' |
61 | ); | 61 | ); |
62 | 62 | ||
diff --git a/tpl/default/configure.html b/tpl/default/configure.html index d6536d47..7469ab59 100644 --- a/tpl/default/configure.html +++ b/tpl/default/configure.html | |||
@@ -73,15 +73,35 @@ | |||
73 | <div class="pure-u-lg-{$ratioLabel} pure-u-1 "> | 73 | <div class="pure-u-lg-{$ratioLabel} pure-u-1 "> |
74 | <div class="form-label"> | 74 | <div class="form-label"> |
75 | <label> | 75 | <label> |
76 | <span class="label-name">{'Timezone'|t}</span> | 76 | <span class="label-name">{'Timezone'|t}</span><br> |
77 | <span class="label-desc">{'Continent'|t} · {'City'|t}</span> | ||
77 | </label> | 78 | </label> |
78 | </div> | 79 | </div> |
79 | </div> | 80 | </div> |
80 | <div class="pure-u-lg-{$ratioInput} pure-u-1 "> | 81 | <div class="pure-u-lg-{$ratioInput} pure-u-1 "> |
81 | <div class="form-input"> | 82 | <div class="form-input"> |
82 | {ignore}FIXME! too hackish, needs to be fixed upstream{/ignore} | 83 | <div class="timezone"> |
83 | <div class="timezone" id="timezone-remove">{$timezone_form}</div> | 84 | <select id="continent" name="continent"> |
84 | <div class="timezone" id="timezone-add"></div> | 85 | {loop="$continents"} |
86 | {if="$key !== 'selected'"} | ||
87 | <option value="{$value}" {if="$continents.selected === $value"}selected{/if}> | ||
88 | {$value} | ||
89 | </option> | ||
90 | {/if} | ||
91 | {/loop} | ||
92 | </select> | ||
93 | <select id="city" name="city"> | ||
94 | {loop="$cities"} | ||
95 | {if="$key !== 'selected'"} | ||
96 | <option value="{$value.city}" | ||
97 | {if="$cities.selected === $value.city"}selected{/if} | ||
98 | data-continent="{$value.continent}"> | ||
99 | {$value.city} | ||
100 | </option> | ||
101 | {/if} | ||
102 | {/loop} | ||
103 | </select> | ||
104 | </div> | ||
85 | </div> | 105 | </div> |
86 | </div> | 106 | </div> |
87 | </div> | 107 | </div> |
@@ -186,7 +206,7 @@ | |||
186 | <div class="pure-g"> | 206 | <div class="pure-g"> |
187 | <div class="pure-u-lg-{$ratioLabel} pure-u-{$ratioLabelMobile}"> | 207 | <div class="pure-u-lg-{$ratioLabel} pure-u-{$ratioLabelMobile}"> |
188 | <div class="form-label"> | 208 | <div class="form-label"> |
189 | <label for="apiEnabled"> | 209 | <label for="enableApi"> |
190 | <span class="label-name">{'Enable REST API'|t}</span><br> | 210 | <span class="label-name">{'Enable REST API'|t}</span><br> |
191 | <span class="label-desc">{'Allow third party software to use Shaarli such as mobile application'|t}</span> | 211 | <span class="label-desc">{'Allow third party software to use Shaarli such as mobile application'|t}</span> |
192 | </label> | 212 | </label> |
@@ -194,7 +214,7 @@ | |||
194 | </div> | 214 | </div> |
195 | <div class="pure-u-lg-{$ratioInput} pure-u-{$ratioInputMobile}"> | 215 | <div class="pure-u-lg-{$ratioInput} pure-u-{$ratioInputMobile}"> |
196 | <div class="form-input"> | 216 | <div class="form-input"> |
197 | <input type="checkbox" name="apiEnabled" id="apiEnabled" | 217 | <input type="checkbox" name="enableApi" id="enableApi" |
198 | {if="$api_enabled"}checked{/if}/> | 218 | {if="$api_enabled"}checked{/if}/> |
199 | </div> | 219 | </div> |
200 | </div> | 220 | </div> |
diff --git a/tpl/default/css/shaarli.css b/tpl/default/css/shaarli.css index 8fcd13af..73fade5f 100644 --- a/tpl/default/css/shaarli.css +++ b/tpl/default/css/shaarli.css | |||
@@ -35,14 +35,29 @@ pre { | |||
35 | } | 35 | } |
36 | 36 | ||
37 | @font-face { | 37 | @font-face { |
38 | font-family: 'Roboto Slab'; | 38 | font-family: 'Roboto'; |
39 | font-weight: 400; | 39 | font-weight: 400; |
40 | font-style: normal; | 40 | font-style: normal; |
41 | src: | 41 | src: |
42 | local('Fira Sans'), | 42 | local('Roboto'), |
43 | local('Fira-Sans-regular'), | 43 | local('Roboto-Regular'), |
44 | url('../fonts/Fira-Sans-regular.woff2') format('woff2'), | 44 | url('../fonts/Roboto-Regular.woff2') format('woff2'), |
45 | url('../fonts/Fira-Sans-regular.woff') format('woff'); | 45 | url('../fonts/Roboto-Regular.woff') format('woff'); |
46 | } | ||
47 | |||
48 | @font-face { | ||
49 | font-family: 'Roboto'; | ||
50 | font-weight: 700; | ||
51 | font-style: normal; | ||
52 | src: | ||
53 | local('Roboto'), | ||
54 | local('Roboto-Bold'), | ||
55 | url('../fonts/Roboto-Bold.woff2') format('woff2'), | ||
56 | url('../fonts/Roboto-Bold.woff') format('woff'); | ||
57 | } | ||
58 | |||
59 | body, .pure-g [class*="pure-u"] { | ||
60 | font-family: Roboto, Arial, sans-serif; | ||
46 | } | 61 | } |
47 | 62 | ||
48 | /** | 63 | /** |
@@ -68,10 +83,6 @@ pre { | |||
68 | .pure-u-xl-visible { display: inline-block !important; } | 83 | .pure-u-xl-visible { display: inline-block !important; } |
69 | } | 84 | } |
70 | 85 | ||
71 | .pure-g [class*="pure-u"]{ | ||
72 | font-family: Roboto Slab, Arial, sans-serif; | ||
73 | } | ||
74 | |||
75 | /** | 86 | /** |
76 | * Make pure-extras alert closable. | 87 | * Make pure-extras alert closable. |
77 | */ | 88 | */ |
@@ -504,7 +515,6 @@ pre { | |||
504 | color: #252525; | 515 | color: #252525; |
505 | text-decoration: none; | 516 | text-decoration: none; |
506 | vertical-align: middle; | 517 | vertical-align: middle; |
507 | font-family: Roboto Slab, Arial, sans-serif; | ||
508 | } | 518 | } |
509 | 519 | ||
510 | .linklist-item-title .linklist-link { | 520 | .linklist-item-title .linklist-link { |
@@ -560,7 +570,6 @@ pre { | |||
560 | .linklist-item-description { | 570 | .linklist-item-description { |
561 | position: relative; | 571 | position: relative; |
562 | padding: 10px; | 572 | padding: 10px; |
563 | font-family: Roboto Slab, Arial, sans-serif; | ||
564 | word-wrap: break-word; | 573 | word-wrap: break-word; |
565 | color: #252525; | 574 | color: #252525; |
566 | line-height: 1.3em; | 575 | line-height: 1.3em; |
diff --git a/tpl/default/daily.html b/tpl/default/daily.html index d8c91078..29d845d5 100644 --- a/tpl/default/daily.html +++ b/tpl/default/daily.html | |||
@@ -44,7 +44,7 @@ | |||
44 | </div> | 44 | </div> |
45 | </div> | 45 | </div> |
46 | <div> | 46 | <div> |
47 | <h3 class="window-subtitle">{function="strftime('%A %d, %B %Y', $day)"}</h3> | 47 | <h3 class="window-subtitle">{function="format_date($dayDate, false)"}</h3> |
48 | 48 | ||
49 | <div id="plugin_zone_about_daily" class="plugin_zone"> | 49 | <div id="plugin_zone_about_daily" class="plugin_zone"> |
50 | {loop="$daily_about_plugin"} | 50 | {loop="$daily_about_plugin"} |
diff --git a/tpl/default/fonts/Fira-Sans-regular.woff b/tpl/default/fonts/Fira-Sans-regular.woff deleted file mode 100644 index 014ac317..00000000 --- a/tpl/default/fonts/Fira-Sans-regular.woff +++ /dev/null | |||
Binary files differ | |||
diff --git a/tpl/default/fonts/Fira-Sans-regular.woff2 b/tpl/default/fonts/Fira-Sans-regular.woff2 deleted file mode 100644 index bf3ad9a4..00000000 --- a/tpl/default/fonts/Fira-Sans-regular.woff2 +++ /dev/null | |||
Binary files differ | |||
diff --git a/tpl/default/fonts/Roboto-Bold.woff b/tpl/default/fonts/Roboto-Bold.woff new file mode 100644 index 00000000..3d86753b --- /dev/null +++ b/tpl/default/fonts/Roboto-Bold.woff | |||
Binary files differ | |||
diff --git a/tpl/default/fonts/Roboto-Bold.woff2 b/tpl/default/fonts/Roboto-Bold.woff2 new file mode 100644 index 00000000..bd05e2ea --- /dev/null +++ b/tpl/default/fonts/Roboto-Bold.woff2 | |||
Binary files differ | |||
diff --git a/tpl/default/fonts/Roboto-Regular.woff b/tpl/default/fonts/Roboto-Regular.woff new file mode 100644 index 00000000..464d2062 --- /dev/null +++ b/tpl/default/fonts/Roboto-Regular.woff | |||
Binary files differ | |||
diff --git a/tpl/default/fonts/Roboto-Regular.woff2 b/tpl/default/fonts/Roboto-Regular.woff2 new file mode 100644 index 00000000..f9661967 --- /dev/null +++ b/tpl/default/fonts/Roboto-Regular.woff2 | |||
Binary files differ | |||
diff --git a/tpl/default/import.html b/tpl/default/import.html index e6e521e8..1f040685 100644 --- a/tpl/default/import.html +++ b/tpl/default/import.html | |||
@@ -18,6 +18,7 @@ | |||
18 | <div class="center" id="import-field"> | 18 | <div class="center" id="import-field"> |
19 | <input type="hidden" name="MAX_FILE_SIZE" value="{$maxfilesize}"> | 19 | <input type="hidden" name="MAX_FILE_SIZE" value="{$maxfilesize}"> |
20 | <input type="file" name="filetoupload"> | 20 | <input type="file" name="filetoupload"> |
21 | <p><br>Maximum size allowed: <strong>{$maxfilesizeHuman}</strong></p> | ||
21 | </div> | 22 | </div> |
22 | 23 | ||
23 | <div class="pure-g"> | 24 | <div class="pure-g"> |
diff --git a/tpl/default/install.html b/tpl/default/install.html index 33f8a453..164d453b 100644 --- a/tpl/default/install.html +++ b/tpl/default/install.html | |||
@@ -7,6 +7,8 @@ | |||
7 | 7 | ||
8 | {$ratioLabel='1-4'} | 8 | {$ratioLabel='1-4'} |
9 | {$ratioInput='3-4'} | 9 | {$ratioInput='3-4'} |
10 | {$ratioLabelMobile='7-8'} | ||
11 | {$ratioInputMobile='1-8'} | ||
10 | 12 | ||
11 | <form method="POST" action="#" name="installform" id="installform"> | 13 | <form method="POST" action="#" name="installform" id="installform"> |
12 | <div class="pure-g"> | 14 | <div class="pure-g"> |
@@ -43,24 +45,22 @@ | |||
43 | </div> | 45 | </div> |
44 | <div class="pure-u-lg-{$ratioInput} pure-u-1"> | 46 | <div class="pure-u-lg-{$ratioInput} pure-u-1"> |
45 | <div class="form-input"> | 47 | <div class="form-input"> |
46 | <input type="text" name="setpassword" id="password"> | 48 | <input type="password" name="setpassword" id="password"> |
47 | </div> | 49 | </div> |
48 | </div> | 50 | </div> |
49 | </div> | 51 | </div> |
50 | 52 | ||
51 | <div class="pure-g"> | 53 | <div class="pure-g"> |
52 | <div class="pure-u-lg-{$ratioLabel} pure-u-1 "> | 54 | <div class="pure-u-lg-{$ratioLabel} pure-u-1"> |
53 | <div class="form-label"> | 55 | <div class="form-label"> |
54 | <label> | 56 | <label for="title"> |
55 | <span class="label-name">{'Timezone'|t}</span> | 57 | <span class="label-name">{'Shaarli title'|t}</span> |
56 | </label> | 58 | </label> |
57 | </div> | 59 | </div> |
58 | </div> | 60 | </div> |
59 | <div class="pure-u-lg-{$ratioInput} pure-u-1 "> | 61 | <div class="pure-u-lg-{$ratioInput} pure-u-1"> |
60 | <div class="form-input"> | 62 | <div class="form-input"> |
61 | {ignore}FIXME! too hackish, needs to be fixed upstream{/ignore} | 63 | <input type="text" name="title" id="title" placeholder="{'My links'|t}"> |
62 | <div class="timezone" id="timezone-remove">{$timezone_html}</div> | ||
63 | <div class="timezone" id="timezone-add"></div> | ||
64 | </div> | 64 | </div> |
65 | </div> | 65 | </div> |
66 | </div> | 66 | </div> |
@@ -68,14 +68,36 @@ | |||
68 | <div class="pure-g"> | 68 | <div class="pure-g"> |
69 | <div class="pure-u-lg-{$ratioLabel} pure-u-1"> | 69 | <div class="pure-u-lg-{$ratioLabel} pure-u-1"> |
70 | <div class="form-label"> | 70 | <div class="form-label"> |
71 | <label for="title"> | 71 | <label> |
72 | <span class="label-name">{'Shaarli title'|t}</span> | 72 | <span class="label-name">{'Timezone'|t}</span><br> |
73 | <span class="label-desc">{'Continent'|t} · {'City'|t}</span> | ||
73 | </label> | 74 | </label> |
74 | </div> | 75 | </div> |
75 | </div> | 76 | </div> |
76 | <div class="pure-u-lg-{$ratioInput} pure-u-1"> | 77 | <div class="pure-u-lg-{$ratioInput} pure-u-1"> |
77 | <div class="form-input"> | 78 | <div class="form-input"> |
78 | <input type="text" name="title" id="title" placeholder="{'My links'|t}"> | 79 | <div class="timezone"> |
80 | <select id="continent" name="continent"> | ||
81 | {loop="$continents"} | ||
82 | {if="$key !== 'selected'"} | ||
83 | <option value="{$value}" {if="$continents.selected === $value"}selected{/if}> | ||
84 | {$value} | ||
85 | </option> | ||
86 | {/if} | ||
87 | {/loop} | ||
88 | </select> | ||
89 | <select id="city" name="city"> | ||
90 | {loop="$cities"} | ||
91 | {if="$key !== 'selected'"} | ||
92 | <option value="{$value.city}" | ||
93 | {if="$cities.selected === $value.city"}selected{/if} | ||
94 | data-continent="{$value.continent}"> | ||
95 | {$value.city} | ||
96 | </option> | ||
97 | {/if} | ||
98 | {/loop} | ||
99 | </select> | ||
100 | </div> | ||
79 | </div> | 101 | </div> |
80 | </div> | 102 | </div> |
81 | </div> | 103 | </div> |
@@ -98,6 +120,22 @@ | |||
98 | </div> | 120 | </div> |
99 | </div> | 121 | </div> |
100 | 122 | ||
123 | <div class="pure-g"> | ||
124 | <div class="pure-u-lg-{$ratioLabel} pure-u-{$ratioLabelMobile}"> | ||
125 | <div class="form-label"> | ||
126 | <label for="enableApi"> | ||
127 | <span class="label-name">{'Enable REST API'|t}</span><br> | ||
128 | <span class="label-desc">{'Allow third party software to use Shaarli such as mobile application'|t}</span> | ||
129 | </label> | ||
130 | </div> | ||
131 | </div> | ||
132 | <div class="pure-u-lg-{$ratioInput} pure-u-{$ratioInputMobile}"> | ||
133 | <div class="form-input"> | ||
134 | <input type="checkbox" name="enableApi" id="enableApi" checked /> | ||
135 | </div> | ||
136 | </div> | ||
137 | </div> | ||
138 | |||
101 | <div class="center"> | 139 | <div class="center"> |
102 | <input type="submit" value="{'Install'|t}" name="Save"> | 140 | <input type="submit" value="{'Install'|t}" name="Save"> |
103 | </div> | 141 | </div> |
diff --git a/tpl/default/js/shaarli.js b/tpl/default/js/shaarli.js index 30d8ed6f..4d47fcd0 100644 --- a/tpl/default/js/shaarli.js +++ b/tpl/default/js/shaarli.js | |||
@@ -76,9 +76,12 @@ window.onload = function () { | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | document.getElementById('menu-toggle').addEventListener('click', function (e) { | 79 | var menuToggle = document.getElementById('menu-toggle'); |
80 | toggleMenu(); | 80 | if (menuToggle != null) { |
81 | }); | 81 | menuToggle.addEventListener('click', function (e) { |
82 | toggleMenu(); | ||
83 | }); | ||
84 | } | ||
82 | 85 | ||
83 | window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu); | 86 | window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu); |
84 | })(this, this.document); | 87 | })(this, this.document); |
@@ -255,10 +258,9 @@ window.onload = function () { | |||
255 | * Remove CSS target padding (for fixed bar) | 258 | * Remove CSS target padding (for fixed bar) |
256 | */ | 259 | */ |
257 | if (location.hash != '') { | 260 | if (location.hash != '') { |
258 | var anchor = document.querySelector(location.hash); | 261 | var anchor = document.getElementById(location.hash.substr(1)); |
259 | if (anchor != null) { | 262 | if (anchor != null) { |
260 | var padsize = anchor.clientHeight; | 263 | var padsize = anchor.clientHeight; |
261 | console.log(document.querySelector(location.hash).clientHeight); | ||
262 | this.window.scroll(0, this.window.scrollY - padsize); | 264 | this.window.scroll(0, this.window.scrollY - padsize); |
263 | anchor.style.paddingTop = 0; | 265 | anchor.style.paddingTop = 0; |
264 | } | 266 | } |
@@ -300,21 +302,6 @@ window.onload = function () { | |||
300 | } | 302 | } |
301 | 303 | ||
302 | /** | 304 | /** |
303 | * TimeZome select | ||
304 | * FIXME! way too hackish | ||
305 | */ | ||
306 | var toRemove = document.getElementById('timezone-remove'); | ||
307 | if (toRemove != null) { | ||
308 | var firstSelect = toRemove.getElementsByTagName('select')[0]; | ||
309 | var secondSelect = toRemove.getElementsByTagName('select')[1]; | ||
310 | toRemove.parentNode.removeChild(toRemove); | ||
311 | var toAdd = document.getElementById('timezone-add'); | ||
312 | var newTimezone = '<span class="timezone-continent">Continent ' + firstSelect.outerHTML + '</span>'; | ||
313 | newTimezone += ' <span class="timezone-country">Country ' + secondSelect.outerHTML + '</span>'; | ||
314 | toAdd.innerHTML = newTimezone; | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * Awesomplete trigger. | 305 | * Awesomplete trigger. |
319 | */ | 306 | */ |
320 | var tags = document.getElementById('lf_tags'); | 307 | var tags = document.getElementById('lf_tags'); |
@@ -366,6 +353,15 @@ window.onload = function () { | |||
366 | } | 353 | } |
367 | }); | 354 | }); |
368 | }); | 355 | }); |
356 | |||
357 | var continent = document.getElementById('continent'); | ||
358 | var city = document.getElementById('city'); | ||
359 | if (continent != null && city != null) { | ||
360 | continent.addEventListener('change', function(event) { | ||
361 | hideTimezoneCities(city, continent.options[continent.selectedIndex].value, true); | ||
362 | }); | ||
363 | hideTimezoneCities(city, continent.options[continent.selectedIndex].value, false); | ||
364 | } | ||
369 | }; | 365 | }; |
370 | 366 | ||
371 | function activateFirefoxSocial(node) { | 367 | function activateFirefoxSocial(node) { |
@@ -391,3 +387,25 @@ function activateFirefoxSocial(node) { | |||
391 | var activate = new CustomEvent("ActivateSocialFeature"); | 387 | var activate = new CustomEvent("ActivateSocialFeature"); |
392 | node.dispatchEvent(activate); | 388 | node.dispatchEvent(activate); |
393 | } | 389 | } |
390 | |||
391 | /** | ||
392 | * Add the class 'hidden' to city options not attached to the current selected continent. | ||
393 | * | ||
394 | * @param cities List of <option> elements | ||
395 | * @param currentContinent Current selected continent | ||
396 | * @param reset Set to true to reset the selected value | ||
397 | */ | ||
398 | function hideTimezoneCities(cities, currentContinent, reset = false) { | ||
399 | var first = true; | ||
400 | [].forEach.call(cities, function(option) { | ||
401 | if (option.getAttribute('data-continent') != currentContinent) { | ||
402 | option.className = 'hidden'; | ||
403 | } else { | ||
404 | option.className = ''; | ||
405 | if (reset === true && first === true) { | ||
406 | option.setAttribute('selected', 'selected'); | ||
407 | first = false; | ||
408 | } | ||
409 | } | ||
410 | }); | ||
411 | } | ||
diff --git a/tpl/vintage/configure.html b/tpl/vintage/configure.html index 5820e6e4..7adc7545 100644 --- a/tpl/vintage/configure.html +++ b/tpl/vintage/configure.html | |||
@@ -4,7 +4,6 @@ | |||
4 | <body onload="document.configform.title.focus();"> | 4 | <body onload="document.configform.title.focus();"> |
5 | <div id="pageheader"> | 5 | <div id="pageheader"> |
6 | {include="page.header"} | 6 | {include="page.header"} |
7 | {$timezone_js} | ||
8 | <form method="POST" action="#" name="configform" id="configform"> | 7 | <form method="POST" action="#" name="configform" id="configform"> |
9 | <input type="hidden" name="token" value="{$token}"> | 8 | <input type="hidden" name="token" value="{$token}"> |
10 | <table id="configuration_table"> | 9 | <table id="configuration_table"> |
@@ -35,7 +34,28 @@ | |||
35 | 34 | ||
36 | <tr> | 35 | <tr> |
37 | <td><b>Timezone:</b></td> | 36 | <td><b>Timezone:</b></td> |
38 | <td>{$timezone_form}</td> | 37 | <td> |
38 | <select id="continent" name="continent"> | ||
39 | {loop="$continents"} | ||
40 | {if="$key !== 'selected'"} | ||
41 | <option value="{$value}" {if="$continents.selected === $value"}selected{/if}> | ||
42 | {$value} | ||
43 | </option> | ||
44 | {/if} | ||
45 | {/loop} | ||
46 | </select> | ||
47 | <select id="city" name="city"> | ||
48 | {loop="$cities"} | ||
49 | {if="$key !== 'selected'"} | ||
50 | <option value="{$value.city}" | ||
51 | {if="$cities.selected === $value.city"}selected{/if} | ||
52 | data-continent="{$value.continent}"> | ||
53 | {$value.city} | ||
54 | </option> | ||
55 | {/if} | ||
56 | {/loop} | ||
57 | </select> | ||
58 | </td> | ||
39 | </tr> | 59 | </tr> |
40 | 60 | ||
41 | <tr> | 61 | <tr> |
@@ -97,9 +117,9 @@ | |||
97 | <tr> | 117 | <tr> |
98 | <td valign="top"><b>Enable REST API</b></td> | 118 | <td valign="top"><b>Enable REST API</b></td> |
99 | <td> | 119 | <td> |
100 | <input type="checkbox" name="apiEnabled" id="apiEnabled" | 120 | <input type="checkbox" name="enableApi" id="enableApi" |
101 | {if="$api_enabled"}checked{/if}/> | 121 | {if="$api_enabled"}checked{/if}/> |
102 | <label for="apiEnabled"> Allow third party software to use Shaarli such as mobile application.</label> | 122 | <label for="enableApi"> Allow third party software to use Shaarli such as mobile application.</label> |
103 | </td> | 123 | </td> |
104 | </tr> | 124 | </tr> |
105 | <tr> | 125 | <tr> |
diff --git a/tpl/vintage/css/shaarli.css b/tpl/vintage/css/shaarli.css index 7ca567e7..9c72d993 100644 --- a/tpl/vintage/css/shaarli.css +++ b/tpl/vintage/css/shaarli.css | |||
@@ -41,6 +41,10 @@ strong { | |||
41 | font-weight: bold; | 41 | font-weight: bold; |
42 | } | 42 | } |
43 | 43 | ||
44 | .hidden { | ||
45 | display: none; | ||
46 | } | ||
47 | |||
44 | /* Buttons */ | 48 | /* Buttons */ |
45 | .bigbutton, #pageheader a.bigbutton { | 49 | .bigbutton, #pageheader a.bigbutton { |
46 | background-color: #c0c0c0; | 50 | background-color: #c0c0c0; |
diff --git a/tpl/vintage/import.html b/tpl/vintage/import.html index 071e1160..bb9e4a56 100644 --- a/tpl/vintage/import.html +++ b/tpl/vintage/import.html | |||
@@ -5,7 +5,7 @@ | |||
5 | <div id="pageheader"> | 5 | <div id="pageheader"> |
6 | {include="page.header"} | 6 | {include="page.header"} |
7 | <div id="uploaddiv"> | 7 | <div id="uploaddiv"> |
8 | Import Netscape HTML bookmarks (as exported from Firefox/Chrome/Opera/Delicious/Diigo...) (Max: {$maxfilesize} bytes). | 8 | Import Netscape HTML bookmarks (as exported from Firefox/Chrome/Opera/Delicious/Diigo...) (Max: {$maxfilesize}). |
9 | <form method="POST" action="?do=import" enctype="multipart/form-data" | 9 | <form method="POST" action="?do=import" enctype="multipart/form-data" |
10 | name="uploadform" id="uploadform"> | 10 | name="uploadform" id="uploadform"> |
11 | <input type="hidden" name="token" value="{$token}"> | 11 | <input type="hidden" name="token" value="{$token}"> |
diff --git a/tpl/vintage/install.html b/tpl/vintage/install.html index 42874dcd..aca890d6 100644 --- a/tpl/vintage/install.html +++ b/tpl/vintage/install.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <!DOCTYPE html> | 1 | <!DOCTYPE html> |
2 | <html> | 2 | <html> |
3 | <head>{include="includes"}{$timezone_js}</head> | 3 | <head>{include="includes"}</head> |
4 | <body onload="document.installform.setlogin.focus();"> | 4 | <body onload="document.installform.setlogin.focus();"> |
5 | <div id="install"> | 5 | <div id="install"> |
6 | <h1>Shaarli</h1> | 6 | <h1>Shaarli</h1> |
@@ -9,7 +9,31 @@ | |||
9 | <table> | 9 | <table> |
10 | <tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr> | 10 | <tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr> |
11 | <tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr> | 11 | <tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr> |
12 | {$timezone_html} | 12 | <tr> |
13 | <td><b>Timezone:</b></td> | ||
14 | <td> | ||
15 | <select id="continent" name="continent"> | ||
16 | {loop="$continents"} | ||
17 | {if="$key !== 'selected'"} | ||
18 | <option value="{$value}" {if="$continents.selected === $value"}selected{/if}> | ||
19 | {$value} | ||
20 | </option> | ||
21 | {/if} | ||
22 | {/loop} | ||
23 | </select> | ||
24 | <select id="city" name="city"> | ||
25 | {loop="$cities"} | ||
26 | {if="$key !== 'selected'"} | ||
27 | <option value="{$value.city}" | ||
28 | {if="$cities.selected === $value.city"}selected{/if} | ||
29 | data-continent="{$value.continent}"> | ||
30 | {$value.city} | ||
31 | </option> | ||
32 | {/if} | ||
33 | {/loop} | ||
34 | </select> | ||
35 | </td> | ||
36 | </tr> | ||
13 | <tr><td><b>Page title:</b></td><td><input type="text" name="title" size="30"></td></tr> | 37 | <tr><td><b>Page title:</b></td><td><input type="text" name="title" size="30"></td></tr> |
14 | <tr><td valign="top"><b>Update:</b></td><td> | 38 | <tr><td valign="top"><b>Update:</b></td><td> |
15 | <input type="checkbox" name="updateCheck" id="updateCheck" checked="checked"><label for="updateCheck"> Notify me when a new release is ready</label></td> | 39 | <input type="checkbox" name="updateCheck" id="updateCheck" checked="checked"><label for="updateCheck"> Notify me when a new release is ready</label></td> |
diff --git a/tpl/vintage/js/shaarli.js b/tpl/vintage/js/shaarli.js new file mode 100644 index 00000000..9bcc96fb --- /dev/null +++ b/tpl/vintage/js/shaarli.js | |||
@@ -0,0 +1,32 @@ | |||
1 | window.onload = function () { | ||
2 | var continent = document.getElementById('continent'); | ||
3 | var city = document.getElementById('city'); | ||
4 | if (continent != null && city != null) { | ||
5 | continent.addEventListener('change', function(event) { | ||
6 | hideTimezoneCities(city, continent.options[continent.selectedIndex].value, true); | ||
7 | }); | ||
8 | hideTimezoneCities(city, continent.options[continent.selectedIndex].value, false); | ||
9 | } | ||
10 | }; | ||
11 | |||
12 | /** | ||
13 | * Add the class 'hidden' to city options not attached to the current selected continent. | ||
14 | * | ||
15 | * @param cities List of <option> elements | ||
16 | * @param currentContinent Current selected continent | ||
17 | * @param reset Set to true to reset the selected value | ||
18 | */ | ||
19 | function hideTimezoneCities(cities, currentContinent, reset = false) { | ||
20 | var first = true; | ||
21 | [].forEach.call(cities, function(option) { | ||
22 | if (option.getAttribute('data-continent') != currentContinent) { | ||
23 | option.className = 'hidden'; | ||
24 | } else { | ||
25 | option.className = ''; | ||
26 | if (reset === true && first === true) { | ||
27 | option.setAttribute('selected', 'selected'); | ||
28 | first = false; | ||
29 | } | ||
30 | } | ||
31 | }); | ||
32 | } | ||
diff --git a/tpl/vintage/page.footer.html b/tpl/vintage/page.footer.html index 006d1d68..4ce0803a 100644 --- a/tpl/vintage/page.footer.html +++ b/tpl/vintage/page.footer.html | |||
@@ -26,6 +26,7 @@ | |||
26 | <script>function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script> | 26 | <script>function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script> |
27 | {/if} | 27 | {/if} |
28 | 28 | ||
29 | <script src="js/shaarli.js"></script> | ||
29 | {loop="$plugins_footer.js_files"} | 30 | {loop="$plugins_footer.js_files"} |
30 | <script src="{$value}#"></script> | 31 | <script src="{$value}#"></script> |
31 | {/loop} | 32 | {/loop} |