diff options
-rw-r--r-- | .dev/.sasslintrc | 8 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | AUTHORS | 10 | ||||
-rw-r--r-- | CHANGELOG.md | 45 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | assets/default/scss/shaarli.scss | 59 | ||||
-rw-r--r-- | doc/md/Plugin-System.md | 17 | ||||
-rw-r--r-- | doc/md/Plugins.md | 4 | ||||
-rw-r--r-- | inc/languages/fr/LC_MESSAGES/shaarli.po | 53 | ||||
-rw-r--r-- | index.php | 25 | ||||
-rw-r--r-- | plugins/default_colors/default_colors.css.template | 3 | ||||
-rw-r--r-- | plugins/default_colors/default_colors.meta | 5 | ||||
-rw-r--r-- | plugins/default_colors/default_colors.php | 111 | ||||
-rw-r--r-- | plugins/demo_plugin/demo_plugin.meta | 3 | ||||
-rw-r--r-- | plugins/demo_plugin/demo_plugin.php | 19 | ||||
-rw-r--r-- | tests/plugins/PluginDefaultColorsTest.php | 195 |
16 files changed, 502 insertions, 60 deletions
diff --git a/.dev/.sasslintrc b/.dev/.sasslintrc index ac406d7b..47c3145d 100644 --- a/.dev/.sasslintrc +++ b/.dev/.sasslintrc | |||
@@ -2,9 +2,11 @@ options: | |||
2 | max-warnings: 0 | 2 | max-warnings: 0 |
3 | rules: | 3 | rules: |
4 | property-sort-order: | 4 | property-sort-order: |
5 | - 1 | 5 | - 0 |
6 | - | 6 | # Sort order rule does not work with CSS variables: https://github.com/sasstools/sass-lint/issues/1161 |
7 | order: 'concentric' | 7 | # - 1 |
8 | # - | ||
9 | # order: 'concentric' | ||
8 | no-important: | 10 | no-important: |
9 | - 0 | 11 | - 0 |
10 | no-vendor-prefixes: | 12 | no-vendor-prefixes: |
@@ -28,6 +28,7 @@ phpdoc.xml | |||
28 | 28 | ||
29 | # User plugin configuration | 29 | # User plugin configuration |
30 | plugins/*/config.php | 30 | plugins/*/config.php |
31 | plugins/default_colors/default_colors.css | ||
31 | 32 | ||
32 | # HTML documentation | 33 | # HTML documentation |
33 | doc/html/ | 34 | doc/html/ |
@@ -1,13 +1,13 @@ | |||
1 | 734 ArthurHoaro <arthur@hoa.ro> | 1 | 769 ArthurHoaro <arthur@hoa.ro> |
2 | 400 VirtualTam <virtualtam@flibidi.net> | 2 | 401 VirtualTam <virtualtam@flibidi.net> |
3 | 215 nodiscc <nodiscc@gmail.com> | 3 | 216 nodiscc <nodiscc@gmail.com> |
4 | 56 Sébastien Sauvage <sebsauvage@sebsauvage.net> | 4 | 56 Sébastien Sauvage <sebsauvage@sebsauvage.net> |
5 | 15 Florian Eula <eula.florian@gmail.com> | 5 | 15 Florian Eula <eula.florian@gmail.com> |
6 | 13 Emilien Klein <emilien@klein.st> | 6 | 13 Emilien Klein <emilien@klein.st> |
7 | 13 Luce Carević <lcarevic@access42.net> | ||
7 | 12 Nicolas Danelon <hi@nicolasmd.com.ar> | 8 | 12 Nicolas Danelon <hi@nicolasmd.com.ar> |
8 | 9 Willi Eggeling <thewilli@gmail.com> | 9 | 9 Willi Eggeling <thewilli@gmail.com> |
9 | 8 Christophe HENRY <christophe.henry@sbgodin.fr> | 10 | 8 Christophe HENRY <christophe.henry@sbgodin.fr> |
10 | 7 Luce Carević <lcarevic@access42.net> | ||
11 | 6 B. van Berkum <dev@dotmpe.com> | 11 | 6 B. van Berkum <dev@dotmpe.com> |
12 | 6 llune <llune@users.noreply.github.com> | 12 | 6 llune <llune@users.noreply.github.com> |
13 | 5 Lucas Cimon <lucas.cimon@gmail.com> | 13 | 5 Lucas Cimon <lucas.cimon@gmail.com> |
@@ -16,6 +16,7 @@ | |||
16 | 4 Alexandre Alapetite <alexandre@alapetite.fr> | 16 | 4 Alexandre Alapetite <alexandre@alapetite.fr> |
17 | 4 David Sferruzza <david.sferruzza@gmail.com> | 17 | 4 David Sferruzza <david.sferruzza@gmail.com> |
18 | 4 Immánuel Fodor <immanuelfactor+github@gmail.com> | 18 | 4 Immánuel Fodor <immanuelfactor+github@gmail.com> |
19 | 3 Agurato <mail.vmonot@gmail.com> | ||
19 | 3 Teromene <teromene@teromene.fr> | 20 | 3 Teromene <teromene@teromene.fr> |
20 | 2 Alexandre G.-Raymond <alex@ndre.gr> | 21 | 2 Alexandre G.-Raymond <alex@ndre.gr> |
21 | 2 Chris Kuethe <chris.kuethe@gmail.com> | 22 | 2 Chris Kuethe <chris.kuethe@gmail.com> |
@@ -57,6 +58,7 @@ | |||
57 | 1 Mark Gerarts <mark.gerarts@gmail.com> | 58 | 1 Mark Gerarts <mark.gerarts@gmail.com> |
58 | 1 Marsup <marsup@gmail.com> | 59 | 1 Marsup <marsup@gmail.com> |
59 | 1 Neros <contact@neros.fr> | 60 | 1 Neros <contact@neros.fr> |
61 | 1 Rajat Hans <rajathans9@gmail.com> | ||
60 | 1 Sbgodin <Sbgodin@users.noreply.github.com> | 62 | 1 Sbgodin <Sbgodin@users.noreply.github.com> |
61 | 1 TsT <tst2005@gmail.com> | 63 | 1 TsT <tst2005@gmail.com> |
62 | 1 dimtion <zizou.xena@gmail.com> | 64 | 1 dimtion <zizou.xena@gmail.com> |
diff --git a/CHANGELOG.md b/CHANGELOG.md index 865e0370..189ed13d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md | |||
@@ -4,6 +4,51 @@ All notable changes to this project will be documented in this file. | |||
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) |
5 | and this project adheres to [Semantic Versioning](http://semver.org/). | 5 | and this project adheres to [Semantic Versioning](http://semver.org/). |
6 | 6 | ||
7 | ## [v0.11.0](https://github.com/shaarli/Shaarli/releases/tag/v0.11.0) - 2019-07-27 | ||
8 | |||
9 | **Shaarli no longer officially support PHP 5.6 and PHP 7.0 as they've reached end of life.** | ||
10 | |||
11 | **Shaarli classes now use namespace, third party plugins need to update.** | ||
12 | |||
13 | ### Added | ||
14 | - Add optional PHP extension to composer suggestions. | ||
15 | - composer: enforce PHP security advisories | ||
16 | - phpDocumentor configuration and make target | ||
17 | - Run unit tests against PHP 7.3 | ||
18 | - Bunch of accessibility improvements to the default template, thanks to @llune | ||
19 | - Bulk actions: set visibility | ||
20 | - Display sticky label in linklist | ||
21 | - Add print CSS rules to the default template | ||
22 | - New setting to automatically retrieve description for new bookmarks | ||
23 | - Plugin to override default template colors | ||
24 | |||
25 | ### Changed | ||
26 | - Shaarli now uses namespaces for its classes. | ||
27 | - Rewrite IP ban management | ||
28 | - Default template: slightly lighten visited link color | ||
29 | - Hide select all button on mobile view | ||
30 | - Switch from FontAwesome v4.x to ForkAwesome | ||
31 | - Daily - display the current day instead of the previous one | ||
32 | |||
33 | ### Fixed | ||
34 | - Do not check the IP address with session protection disabled | ||
35 | - API: update test regexes to comply with PCRE2 | ||
36 | - Optimize and cleanup imports | ||
37 | - ensure HTML tags are stripped from OpenGraph description | ||
38 | - Documentation invalid links | ||
39 | - Thumbnails disabling if PHP GD is not installed | ||
40 | - Warning if links sticky status isn't set | ||
41 | - Fix button overlapping on mobile in linklist | ||
42 | - Do not try to retrieve thumbnails for internal link | ||
43 | - Update node-sass to fix a vulnerability in node tar dependency | ||
44 | - armhf Dockerfile | ||
45 | - Default template: Responsive issue with delete button fix | ||
46 | - Persist sticky status on bookmark update | ||
47 | |||
48 | ### Removed | ||
49 | - Doxygen configuration | ||
50 | - redirector setting | ||
51 | - QRCode link to an external service | ||
7 | 52 | ||
8 | ## [v0.10.4](https://github.com/shaarli/Shaarli/releases/tag/v0.10.4) - 2019-04-16 | 53 | ## [v0.10.4](https://github.com/shaarli/Shaarli/releases/tag/v0.10.4) - 2019-04-16 |
9 | ### Fixed | 54 | ### Fixed |
@@ -6,10 +6,10 @@ _Do you want to share the links you discover?_ | |||
6 | _Shaarli is a minimalist link sharing service that you can install on your own server._ | 6 | _Shaarli is a minimalist link sharing service 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/badge/stable-v0.9.7-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.9.7) | 9 | [![](https://img.shields.io/badge/stable-v0.10.4-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.10.4) |
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 | • | 11 | • |
12 | [![](https://img.shields.io/badge/latest-v0.10.4-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.10.4) | 12 | [![](https://img.shields.io/badge/latest-v0.11.0-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.11.0) |
13 | [![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli) | 13 | [![](https://img.shields.io/travis/shaarli/Shaarli/latest.svg?label=latest)](https://travis-ci.org/shaarli/Shaarli) |
14 | • | 14 | • |
15 | [![](https://img.shields.io/badge/master-v0.11.x-blue.svg)](https://github.com/shaarli/Shaarli) | 15 | [![](https://img.shields.io/badge/master-v0.11.x-blue.svg)](https://github.com/shaarli/Shaarli) |
diff --git a/assets/default/scss/shaarli.scss b/assets/default/scss/shaarli.scss index 9e5464a0..61e382b6 100644 --- a/assets/default/scss/shaarli.scss +++ b/assets/default/scss/shaarli.scss | |||
@@ -25,9 +25,15 @@ $warning-text: #97600d; | |||
25 | $form-input-border: #d8d8d8; | 25 | $form-input-border: #d8d8d8; |
26 | $form-input-background: #eee; | 26 | $form-input-background: #eee; |
27 | 27 | ||
28 | :root { | ||
29 | --main-color: #{$main-green}; | ||
30 | --background-color: #{$background-color}; | ||
31 | --dark-main-color: #{$dark-green}; | ||
32 | } | ||
33 | |||
28 | // General | 34 | // General |
29 | body { | 35 | body { |
30 | background: $background-color; | 36 | background: var(--background-color); |
31 | } | 37 | } |
32 | 38 | ||
33 | .strong { | 39 | .strong { |
@@ -143,7 +149,7 @@ body, | |||
143 | } | 149 | } |
144 | 150 | ||
145 | .pure-alert-success { | 151 | .pure-alert-success { |
146 | background-color: $main-green; | 152 | background-color: var(--main-color); |
147 | } | 153 | } |
148 | 154 | ||
149 | .pure-alert-warning { | 155 | .pure-alert-warning { |
@@ -169,7 +175,7 @@ body, | |||
169 | top: 0; | 175 | top: 0; |
170 | transition: max-height .5s; | 176 | transition: max-height .5s; |
171 | z-index: 999; | 177 | z-index: 999; |
172 | background: $main-green; | 178 | background: var(--main-color); |
173 | width: 100%; | 179 | width: 100%; |
174 | // Hack to transition with auto height: http://stackoverflow.com/a/8331169/1484919 | 180 | // Hack to transition with auto height: http://stackoverflow.com/a/8331169/1484919 |
175 | max-height: 45px; | 181 | max-height: 45px; |
@@ -322,7 +328,7 @@ body, | |||
322 | button { | 328 | button { |
323 | border: 0; | 329 | border: 0; |
324 | border-radius: 2px; | 330 | border-radius: 2px; |
325 | background-color: $main-green; | 331 | background-color: var(--main-color); |
326 | padding: 4px 8px 6px; | 332 | padding: 4px 8px 6px; |
327 | color: $almost-white; | 333 | color: $almost-white; |
328 | } | 334 | } |
@@ -358,7 +364,7 @@ body, | |||
358 | .search-tagcloud { | 364 | .search-tagcloud { |
359 | button { | 365 | button { |
360 | &:hover { | 366 | &:hover { |
361 | color: $background-color; | 367 | color: var(--background-color); |
362 | } | 368 | } |
363 | } | 369 | } |
364 | } | 370 | } |
@@ -389,7 +395,7 @@ body, | |||
389 | position: fixed; | 395 | position: fixed; |
390 | visibility: hidden; | 396 | visibility: hidden; |
391 | z-index: 999; | 397 | z-index: 999; |
392 | background: $main-green; | 398 | background: var(--main-color); |
393 | padding: 5px 0; | 399 | padding: 5px 0; |
394 | width: 100%; | 400 | width: 100%; |
395 | height: 30px; | 401 | height: 30px; |
@@ -411,7 +417,7 @@ body, | |||
411 | margin: 0 0 5px; | 417 | margin: 0 0 5px; |
412 | border: 1px solid $almost-white; | 418 | border: 1px solid $almost-white; |
413 | border-radius: 2px; | 419 | border-radius: 2px; |
414 | background: $main-green; | 420 | background: var(--main-color); |
415 | padding: 4px 0; | 421 | padding: 4px 0; |
416 | width: 100px; | 422 | width: 100px; |
417 | height: 28px; | 423 | height: 28px; |
@@ -419,7 +425,7 @@ body, | |||
419 | 425 | ||
420 | &:hover { | 426 | &:hover { |
421 | background: $almost-white; | 427 | background: $almost-white; |
422 | color: $main-green; | 428 | color: var(--main-color); |
423 | } | 429 | } |
424 | } | 430 | } |
425 | 431 | ||
@@ -558,7 +564,7 @@ body, | |||
558 | } | 564 | } |
559 | 565 | ||
560 | .filter-on { | 566 | .filter-on { |
561 | background: $main-green; | 567 | background: var(--main-color); |
562 | color: $light-green; | 568 | color: $light-green; |
563 | } | 569 | } |
564 | 570 | ||
@@ -697,7 +703,7 @@ body, | |||
697 | 703 | ||
698 | &:visited { | 704 | &:visited { |
699 | .linklist-link { | 705 | .linklist-link { |
700 | color: $dark-green; | 706 | color: var(--dark-main-color); |
701 | } | 707 | } |
702 | } | 708 | } |
703 | 709 | ||
@@ -708,7 +714,7 @@ body, | |||
708 | } | 714 | } |
709 | 715 | ||
710 | .linklist-link { | 716 | .linklist-link { |
711 | color: $main-green; | 717 | color: var(--main-color); |
712 | font-size: 1.1em; | 718 | font-size: 1.1em; |
713 | 719 | ||
714 | &:hover { | 720 | &:hover { |
@@ -783,14 +789,14 @@ body, | |||
783 | 789 | ||
784 | a { | 790 | a { |
785 | text-decoration: none; | 791 | text-decoration: none; |
786 | color: $main-green; | 792 | color: var(--main-color); |
787 | 793 | ||
788 | &:hover { | 794 | &:hover { |
789 | color: $dark-grey; | 795 | color: $dark-grey; |
790 | } | 796 | } |
791 | 797 | ||
792 | &:visited { | 798 | &:visited { |
793 | color: $dark-green; | 799 | color: var(--dark-main-color); |
794 | } | 800 | } |
795 | } | 801 | } |
796 | } | 802 | } |
@@ -888,7 +894,7 @@ body, | |||
888 | &::before { | 894 | &::before { |
889 | display: block; | 895 | display: block; |
890 | margin: 10px auto; | 896 | margin: 10px auto; |
891 | background: linear-gradient(to right, $background-color, $dark-grey, $background-color); | 897 | background: linear-gradient(to right, var(--background-color), $dark-grey, var(--background-color)); |
892 | width: 80%; | 898 | width: 80%; |
893 | height: 1px; | 899 | height: 1px; |
894 | content: ''; | 900 | content: ''; |
@@ -917,7 +923,7 @@ body, | |||
917 | margin: 15px 5px; | 923 | margin: 15px 5px; |
918 | border: 0; | 924 | border: 0; |
919 | box-shadow: 1px 1px 1px $form-input-border, -1px -1px 6px $form-input-border, -1px 1px 2px $form-input-border, 1px -1px 2px $form-input-border; | 925 | box-shadow: 1px 1px 1px $form-input-border, -1px -1px 6px $form-input-border, -1px 1px 2px $form-input-border, 1px -1px 2px $form-input-border; |
920 | background: $main-green; | 926 | background: var(--main-color); |
921 | min-width: 150px; | 927 | min-width: 150px; |
922 | height: 35px; | 928 | height: 35px; |
923 | vertical-align: center; | 929 | vertical-align: center; |
@@ -941,7 +947,7 @@ body, | |||
941 | padding: 10px 0; | 947 | padding: 10px 0; |
942 | width: 100%; | 948 | width: 100%; |
943 | text-align: center; | 949 | text-align: center; |
944 | color: $main-green; | 950 | color: var(--main-color); |
945 | } | 951 | } |
946 | 952 | ||
947 | .window-subtitle { | 953 | .window-subtitle { |
@@ -950,7 +956,7 @@ body, | |||
950 | 956 | ||
951 | a { | 957 | a { |
952 | text-decoration: none; | 958 | text-decoration: none; |
953 | color: $main-green; | 959 | color: var(--main-color); |
954 | font-weight: bold; | 960 | font-weight: bold; |
955 | 961 | ||
956 | &.button { | 962 | &.button { |
@@ -1072,7 +1078,6 @@ body, | |||
1072 | .page-form { | 1078 | .page-form { |
1073 | .submit-buttons { | 1079 | .submit-buttons { |
1074 | .button { | 1080 | .button { |
1075 | display: block; | ||
1076 | margin: auto; | 1081 | margin: auto; |
1077 | } | 1082 | } |
1078 | } | 1083 | } |
@@ -1278,7 +1283,7 @@ form { | |||
1278 | 1283 | ||
1279 | .pure-button { | 1284 | .pure-button { |
1280 | &:hover { | 1285 | &:hover { |
1281 | background-color: $main-green; | 1286 | background-color: var(--main-color); |
1282 | background-image: none; | 1287 | background-image: none; |
1283 | color: $almost-white; | 1288 | color: $almost-white; |
1284 | } | 1289 | } |
@@ -1362,7 +1367,7 @@ form { | |||
1362 | } | 1367 | } |
1363 | 1368 | ||
1364 | .validate-rename-tag { | 1369 | .validate-rename-tag { |
1365 | color: $main-green; | 1370 | color: var(--main-color); |
1366 | } | 1371 | } |
1367 | } | 1372 | } |
1368 | 1373 | ||
@@ -1458,7 +1463,7 @@ form { | |||
1458 | &::after { | 1463 | &::after { |
1459 | display: block; | 1464 | display: block; |
1460 | margin: 10px auto; | 1465 | margin: 10px auto; |
1461 | background: linear-gradient(to right, $background-color, $dark-grey, $background-color); | 1466 | background: linear-gradient(to right, var(--background-color), $dark-grey, var(--background-color)); |
1462 | width: 90%; | 1467 | width: 90%; |
1463 | height: 1px; | 1468 | height: 1px; |
1464 | content: ''; | 1469 | content: ''; |
@@ -1508,14 +1513,14 @@ form { | |||
1508 | .daily-entry-description { | 1513 | .daily-entry-description { |
1509 | a { | 1514 | a { |
1510 | text-decoration: none; | 1515 | text-decoration: none; |
1511 | color: $main-green; | 1516 | color: var(--main-color); |
1512 | 1517 | ||
1513 | &:hover { | 1518 | &:hover { |
1514 | text-shadow: 1px 1px $background-linklist-info; | 1519 | text-shadow: 1px 1px $background-linklist-info; |
1515 | } | 1520 | } |
1516 | 1521 | ||
1517 | &:visited { | 1522 | &:visited { |
1518 | color: $dark-green; | 1523 | color: var(--dark-main-color); |
1519 | } | 1524 | } |
1520 | } | 1525 | } |
1521 | } | 1526 | } |
@@ -1572,12 +1577,12 @@ form { | |||
1572 | } | 1577 | } |
1573 | 1578 | ||
1574 | .pure-button-shaarli { | 1579 | .pure-button-shaarli { |
1575 | background-color: $main-green; | 1580 | background-color: var(--main-color); |
1576 | } | 1581 | } |
1577 | 1582 | ||
1578 | .progressbar { | 1583 | .progressbar { |
1579 | border-radius: 6px; | 1584 | border-radius: 6px; |
1580 | background-color: $main-green; | 1585 | background-color: var(--main-color); |
1581 | padding: 1px; | 1586 | padding: 1px; |
1582 | 1587 | ||
1583 | > div { | 1588 | > div { |
@@ -1586,8 +1591,8 @@ form { | |||
1586 | -45deg, | 1591 | -45deg, |
1587 | $almost-white, | 1592 | $almost-white, |
1588 | $almost-white 6px, | 1593 | $almost-white 6px, |
1589 | $background-color 6px, | 1594 | var(--background-color) 6px, |
1590 | $background-color 12px | 1595 | var(--background-color) 12px |
1591 | ); | 1596 | ); |
1592 | width: 0%; | 1597 | width: 0%; |
1593 | height: 10px; | 1598 | height: 10px; |
diff --git a/doc/md/Plugin-System.md b/doc/md/Plugin-System.md index cbec04c0..9b0d3a7d 100644 --- a/doc/md/Plugin-System.md +++ b/doc/md/Plugin-System.md | |||
@@ -137,6 +137,7 @@ If it's still not working, please [open an issue](https://github.com/shaarli/Sha | |||
137 | | [render_feed](#render_feed) | Allow to do add tags in RSS and ATOM feeds. | | 137 | | [render_feed](#render_feed) | Allow to do add tags in RSS and ATOM feeds. | |
138 | | [save_link](#save_link) | Allow to alter the link being saved in the datastore. | | 138 | | [save_link](#save_link) | Allow to alter the link being saved in the datastore. | |
139 | | [delete_link](#delete_link) | Allow to do an action before a link is deleted from the datastore. | | 139 | | [delete_link](#delete_link) | Allow to do an action before a link is deleted from the datastore. | |
140 | | [save_plugin_parameters](#save_plugin_parameters) | Allow to manipulate plugin parameters before they're saved. | | ||
140 | 141 | ||
141 | 142 | ||
142 | 143 | ||
@@ -471,6 +472,22 @@ Allow to execute any action before the link is actually removed from the datasto | |||
471 | - created | 472 | - created |
472 | - updated | 473 | - updated |
473 | 474 | ||
475 | |||
476 | #### save_plugin_parameters | ||
477 | |||
478 | Triggered when the plugin parameters are saved from the plugin administration page. | ||
479 | |||
480 | Plugins can perform an action every times their settings are updated. | ||
481 | For example it is used to update the CSS file of the `default_colors` plugins. | ||
482 | |||
483 | ##### Data | ||
484 | |||
485 | `$data` input contains the `$_POST` array. | ||
486 | |||
487 | So if the plugin has a parameter called `MYPLUGIN_PARAMETER`, | ||
488 | the array will contain an entry with `MYPLUGIN_PARAMETER` as a key. | ||
489 | |||
490 | |||
474 | ## Guide for template designer | 491 | ## Guide for template designer |
475 | 492 | ||
476 | ### Plugin administration | 493 | ### Plugin administration |
diff --git a/doc/md/Plugins.md b/doc/md/Plugins.md index 954442e2..3e261815 100644 --- a/doc/md/Plugins.md +++ b/doc/md/Plugins.md | |||
@@ -63,8 +63,12 @@ Usage of each plugin is documented in it's README file: | |||
63 | 63 | ||
64 | * `addlink-toolbar`: Adds the addlink input on the linklist page | 64 | * `addlink-toolbar`: Adds the addlink input on the linklist page |
65 | * `archiveorg`: For each link, add an Archive.org icon | 65 | * `archiveorg`: For each link, add an Archive.org icon |
66 | * `default_colors`: Override default theme colors. | ||
67 | * `isso`: Let visitor comment your shaares on permalinks with Isso. | ||
66 | * [`markdown`](https://github.com/shaarli/Shaarli/blob/master/plugins/markdown/README.md): Render shaare description with Markdown syntax. | 68 | * [`markdown`](https://github.com/shaarli/Shaarli/blob/master/plugins/markdown/README.md): Render shaare description with Markdown syntax. |
69 | * `piwik`: A plugin that adds Piwik tracking code to Shaarli pages. | ||
67 | * [`playvideos`](https://github.com/shaarli/Shaarli/blob/master/plugins/playvideos/README.md): Add a button in the toolbar allowing to watch all videos. | 70 | * [`playvideos`](https://github.com/shaarli/Shaarli/blob/master/plugins/playvideos/README.md): Add a button in the toolbar allowing to watch all videos. |
71 | * `pubsubhubbub`: Enable PubSubHubbub feed publishing | ||
68 | * `qrcode`: For each link, add a QRCode icon. | 72 | * `qrcode`: For each link, add a QRCode icon. |
69 | * [`wallabag`](https://github.com/shaarli/Shaarli/blob/master/plugins/wallabag/README.md): For each link, add a Wallabag icon to save it in your instance. | 73 | * [`wallabag`](https://github.com/shaarli/Shaarli/blob/master/plugins/wallabag/README.md): For each link, add a Wallabag icon to save it in your instance. |
70 | 74 | ||
diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po index 611296f1..026d0101 100644 --- a/inc/languages/fr/LC_MESSAGES/shaarli.po +++ b/inc/languages/fr/LC_MESSAGES/shaarli.po | |||
@@ -1,8 +1,8 @@ | |||
1 | msgid "" | 1 | msgid "" |
2 | msgstr "" | 2 | msgstr "" |
3 | "Project-Id-Version: Shaarli\n" | 3 | "Project-Id-Version: Shaarli\n" |
4 | "POT-Creation-Date: 2019-07-06 12:14+0200\n" | 4 | "POT-Creation-Date: 2019-07-13 10:45+0200\n" |
5 | "PO-Revision-Date: 2019-07-06 12:17+0200\n" | 5 | "PO-Revision-Date: 2019-07-13 10:49+0200\n" |
6 | "Last-Translator: \n" | 6 | "Last-Translator: \n" |
7 | "Language-Team: Shaarli\n" | 7 | "Language-Team: Shaarli\n" |
8 | "Language: fr_FR\n" | 8 | "Language: fr_FR\n" |
@@ -403,7 +403,7 @@ msgstr "Note : " | |||
403 | 403 | ||
404 | #: index.php:1424 | 404 | #: index.php:1424 |
405 | msgid "Invalid link ID provided" | 405 | msgid "Invalid link ID provided" |
406 | msgstr "" | 406 | msgstr "ID du lien non valide" |
407 | 407 | ||
408 | #: index.php:1444 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 | 408 | #: index.php:1444 tmp/export.b91ef64efc3688266305ea9b42e5017e.rtpl.php:65 |
409 | msgid "Export" | 409 | msgid "Export" |
@@ -428,15 +428,15 @@ msgstr "" | |||
428 | msgid "Plugin administration" | 428 | msgid "Plugin administration" |
429 | msgstr "Administration des plugins" | 429 | msgstr "Administration des plugins" |
430 | 430 | ||
431 | #: index.php:1615 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | 431 | #: index.php:1616 tmp/thumbnails.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 |
432 | msgid "Thumbnails update" | 432 | msgid "Thumbnails update" |
433 | msgstr "Mise à jour des miniatures" | 433 | msgstr "Mise à jour des miniatures" |
434 | 434 | ||
435 | #: index.php:1781 | 435 | #: index.php:1782 |
436 | msgid "Search: " | 436 | msgid "Search: " |
437 | msgstr "Recherche : " | 437 | msgstr "Recherche : " |
438 | 438 | ||
439 | #: index.php:1824 | 439 | #: index.php:1825 |
440 | #, php-format | 440 | #, php-format |
441 | msgid "" | 441 | msgid "" |
442 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " | 442 | "<pre>Sessions do not seem to work correctly on your server.<br>Make sure the " |
@@ -455,7 +455,7 @@ msgstr "" | |||
455 | "des cookies. Nous vous recommandons d'accéder à votre serveur depuis son " | 455 | "des cookies. Nous vous recommandons d'accéder à votre serveur depuis son " |
456 | "adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>" | 456 | "adresse IP ou un <em>Fully Qualified Domain Name</em>.<br>" |
457 | 457 | ||
458 | #: index.php:1834 | 458 | #: index.php:1835 |
459 | msgid "Click to try again." | 459 | msgid "Click to try again." |
460 | msgstr "Cliquer ici pour réessayer." | 460 | msgstr "Cliquer ici pour réessayer." |
461 | 461 | ||
@@ -480,7 +480,33 @@ msgstr "Voir sur archive.org" | |||
480 | msgid "For each link, add an Archive.org icon." | 480 | msgid "For each link, add an Archive.org icon." |
481 | msgstr "Pour chaque lien, ajoute une icône pour Archive.org." | 481 | msgstr "Pour chaque lien, ajoute une icône pour Archive.org." |
482 | 482 | ||
483 | #: plugins/demo_plugin/demo_plugin.php:465 | 483 | #: plugins/default_colors/default_colors.php:33 |
484 | msgid "" | ||
485 | "Default colors plugin error: This plugin is active and no custom color is " | ||
486 | "configured." | ||
487 | msgstr "" | ||
488 | "Erreur du plugin default colors : ce plugin est actif et aucune couleur " | ||
489 | "n'est configurée." | ||
490 | |||
491 | #: plugins/default_colors/default_colors.php:107 | ||
492 | msgid "Override default theme colors. Use any CSS valid color." | ||
493 | msgstr "" | ||
494 | "Remplacer les couleurs du thème par défaut. Utiliser n'importe quelle " | ||
495 | "couleur CSS valide." | ||
496 | |||
497 | #: plugins/default_colors/default_colors.php:108 | ||
498 | msgid "Main color (navbar green)" | ||
499 | msgstr "Couleur principale (vert de la barre de navigation)" | ||
500 | |||
501 | #: plugins/default_colors/default_colors.php:109 | ||
502 | msgid "Background color (light grey)" | ||
503 | msgstr "Couleur de fond (gris léger)" | ||
504 | |||
505 | #: plugins/default_colors/default_colors.php:110 | ||
506 | msgid "Dark main color (e.g. visited links)" | ||
507 | msgstr "Couleur principale sombre (ex : les liens visités)" | ||
508 | |||
509 | #: plugins/demo_plugin/demo_plugin.php:482 | ||
484 | msgid "" | 510 | msgid "" |
485 | "A demo plugin covering all use cases for template designers and plugin " | 511 | "A demo plugin covering all use cases for template designers and plugin " |
486 | "developers." | 512 | "developers." |
@@ -488,6 +514,14 @@ msgstr "" | |||
488 | "Une extension de démonstration couvrant tous les cas d'utilisation pour les " | 514 | "Une extension de démonstration couvrant tous les cas d'utilisation pour les " |
489 | "designers de thèmes et les développeurs d'extensions." | 515 | "designers de thèmes et les développeurs d'extensions." |
490 | 516 | ||
517 | #: plugins/demo_plugin/demo_plugin.php:483 | ||
518 | msgid "This is a parameter dedicated to the demo plugin. It'll be suffixed." | ||
519 | msgstr "Ceci est un paramètre dédié au plugin de démo. Il sera suffixé." | ||
520 | |||
521 | #: plugins/demo_plugin/demo_plugin.php:484 | ||
522 | msgid "Other demo parameter" | ||
523 | msgstr "Un autre paramètre de démo" | ||
524 | |||
491 | #: plugins/isso/isso.php:22 | 525 | #: plugins/isso/isso.php:22 |
492 | msgid "" | 526 | msgid "" |
493 | "Isso plugin error: Please define the \"ISSO_SERVER\" setting in the plugin " | 527 | "Isso plugin error: Please define the \"ISSO_SERVER\" setting in the plugin " |
@@ -703,9 +737,8 @@ msgstr "" | |||
703 | "miniatures." | 737 | "miniatures." |
704 | 738 | ||
705 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:162 | 739 | #: tmp/configure.90100d2eaf5d3705e14b9b4f78ecddc9.rtpl.php:162 |
706 | #| msgid "Enable thumbnails" | ||
707 | msgid "Synchonize thumbnails" | 740 | msgid "Synchonize thumbnails" |
708 | msgstr "" | 741 | msgstr "Synchroniser les miniatures" |
709 | 742 | ||
710 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 | 743 | #: tmp/configure.b91ef64efc3688266305ea9b42e5017e.rtpl.php:29 |
711 | msgid "title" | 744 | msgid "title" |
@@ -1126,22 +1126,24 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1126 | 1126 | ||
1127 | // lf_id should only be present if the link exists. | 1127 | // lf_id should only be present if the link exists. |
1128 | $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId(); | 1128 | $id = isset($_POST['lf_id']) ? intval(escape($_POST['lf_id'])) : $LINKSDB->getNextId(); |
1129 | $link['id'] = $id; | ||
1129 | // Linkdate is kept here to: | 1130 | // Linkdate is kept here to: |
1130 | // - use the same permalink for notes as they're displayed when creating them | 1131 | // - use the same permalink for notes as they're displayed when creating them |
1131 | // - let users hack creation date of their posts | 1132 | // - let users hack creation date of their posts |
1132 | // See: https://shaarli.readthedocs.io/en/master/guides/various-hacks/#changing-the-timestamp-for-a-shaare | 1133 | // See: https://shaarli.readthedocs.io/en/master/guides/various-hacks/#changing-the-timestamp-for-a-shaare |
1133 | $linkdate = escape($_POST['lf_linkdate']); | 1134 | $linkdate = escape($_POST['lf_linkdate']); |
1135 | $link['created'] = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate); | ||
1134 | if (isset($LINKSDB[$id])) { | 1136 | if (isset($LINKSDB[$id])) { |
1135 | // Edit | 1137 | // Edit |
1136 | $created = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate); | 1138 | $link['updated'] = new DateTime(); |
1137 | $updated = new DateTime(); | 1139 | $link['shorturl'] = $LINKSDB[$id]['shorturl']; |
1138 | $shortUrl = $LINKSDB[$id]['shorturl']; | 1140 | $link['sticky'] = isset($LINKSDB[$id]['sticky']) ? $LINKSDB[$id]['sticky'] : false; |
1139 | $new = false; | 1141 | $new = false; |
1140 | } else { | 1142 | } else { |
1141 | // New link | 1143 | // New link |
1142 | $created = DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, $linkdate); | 1144 | $link['updated'] = null; |
1143 | $updated = null; | 1145 | $link['shorturl'] = link_small_hash($link['created'], $id); |
1144 | $shortUrl = link_small_hash($created, $id); | 1146 | $link['sticky'] = false; |
1145 | $new = true; | 1147 | $new = true; |
1146 | } | 1148 | } |
1147 | 1149 | ||
@@ -1157,17 +1159,13 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1157 | } | 1159 | } |
1158 | $url = whitelist_protocols(trim($_POST['lf_url']), $conf->get('security.allowed_protocols')); | 1160 | $url = whitelist_protocols(trim($_POST['lf_url']), $conf->get('security.allowed_protocols')); |
1159 | 1161 | ||
1160 | $link = array( | 1162 | $link = array_merge($link, [ |
1161 | 'id' => $id, | ||
1162 | 'title' => trim($_POST['lf_title']), | 1163 | 'title' => trim($_POST['lf_title']), |
1163 | 'url' => $url, | 1164 | 'url' => $url, |
1164 | 'description' => $_POST['lf_description'], | 1165 | 'description' => $_POST['lf_description'], |
1165 | 'private' => (isset($_POST['lf_private']) ? 1 : 0), | 1166 | 'private' => (isset($_POST['lf_private']) ? 1 : 0), |
1166 | 'created' => $created, | ||
1167 | 'updated' => $updated, | ||
1168 | 'tags' => str_replace(',', ' ', $tags), | 1167 | 'tags' => str_replace(',', ' ', $tags), |
1169 | 'shorturl' => $shortUrl, | 1168 | ]); |
1170 | ); | ||
1171 | 1169 | ||
1172 | // If title is empty, use the URL as title. | 1170 | // If title is empty, use the URL as title. |
1173 | if ($link['title'] == '') { | 1171 | if ($link['title'] == '') { |
@@ -1181,8 +1179,6 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1181 | $link['thumbnail'] = $thumbnailer->get($url); | 1179 | $link['thumbnail'] = $thumbnailer->get($url); |
1182 | } | 1180 | } |
1183 | 1181 | ||
1184 | $link['sticky'] = isset($link['sticky']) ? $link['sticky'] : false; | ||
1185 | |||
1186 | $pluginManager->executeHooks('save_link', $link); | 1182 | $pluginManager->executeHooks('save_link', $link); |
1187 | 1183 | ||
1188 | $LINKSDB[$id] = $link; | 1184 | $LINKSDB[$id] = $link; |
@@ -1567,6 +1563,7 @@ function renderPage($conf, $pluginManager, $LINKSDB, $history, $sessionManager, | |||
1567 | if ($targetPage == Router::$PAGE_SAVE_PLUGINSADMIN) { | 1563 | if ($targetPage == Router::$PAGE_SAVE_PLUGINSADMIN) { |
1568 | try { | 1564 | try { |
1569 | if (isset($_POST['parameters_form'])) { | 1565 | if (isset($_POST['parameters_form'])) { |
1566 | $pluginManager->executeHooks('save_plugin_parameters', $_POST); | ||
1570 | unset($_POST['parameters_form']); | 1567 | unset($_POST['parameters_form']); |
1571 | foreach ($_POST as $param => $value) { | 1568 | foreach ($_POST as $param => $value) { |
1572 | $conf->set('plugins.'. $param, escape($value)); | 1569 | $conf->set('plugins.'. $param, escape($value)); |
diff --git a/plugins/default_colors/default_colors.css.template b/plugins/default_colors/default_colors.css.template new file mode 100644 index 00000000..87e22a08 --- /dev/null +++ b/plugins/default_colors/default_colors.css.template | |||
@@ -0,0 +1,3 @@ | |||
1 | :root { | ||
2 | %s | ||
3 | } | ||
diff --git a/plugins/default_colors/default_colors.meta b/plugins/default_colors/default_colors.meta new file mode 100644 index 00000000..108962c6 --- /dev/null +++ b/plugins/default_colors/default_colors.meta | |||
@@ -0,0 +1,5 @@ | |||
1 | description="Override default theme colors. Use any CSS valid color." | ||
2 | parameters="DEFAULT_COLORS_MAIN;DEFAULT_COLORS_BACKGROUND;DEFAULT_COLORS_DARK_MAIN" | ||
3 | parameter.DEFAULT_COLORS_MAIN="Main color (navbar green)" | ||
4 | parameter.DEFAULT_COLORS_BACKGROUND="Background color (light grey)" | ||
5 | parameter.DEFAULT_COLORS_DARK_MAIN="Dark main color (e.g. visited links)" | ||
diff --git a/plugins/default_colors/default_colors.php b/plugins/default_colors/default_colors.php new file mode 100644 index 00000000..1928cc9f --- /dev/null +++ b/plugins/default_colors/default_colors.php | |||
@@ -0,0 +1,111 @@ | |||
1 | <?php | ||
2 | |||
3 | /** | ||
4 | * Plugin default_colors. | ||
5 | * | ||
6 | * Allow users to easily overrides colors of the default theme. | ||
7 | */ | ||
8 | |||
9 | use Shaarli\Config\ConfigManager; | ||
10 | use Shaarli\Plugin\PluginManager; | ||
11 | |||
12 | const DEFAULT_COLORS_PLACEHOLDERS = [ | ||
13 | 'DEFAULT_COLORS_MAIN', | ||
14 | 'DEFAULT_COLORS_BACKGROUND', | ||
15 | 'DEFAULT_COLORS_DARK_MAIN', | ||
16 | ]; | ||
17 | |||
18 | /** | ||
19 | * Display an error if the plugin is active a no color is configured. | ||
20 | * | ||
21 | * @param $conf ConfigManager instance | ||
22 | * | ||
23 | * @return array|null The errors array or null of there is none. | ||
24 | */ | ||
25 | function default_colors_init($conf) | ||
26 | { | ||
27 | $params = ''; | ||
28 | foreach (DEFAULT_COLORS_PLACEHOLDERS as $placeholder) { | ||
29 | $params .= trim($conf->get('plugins.'. $placeholder, '')); | ||
30 | } | ||
31 | |||
32 | if (empty($params)) { | ||
33 | $error = t('Default colors plugin error: '. | ||
34 | 'This plugin is active and no custom color is configured.'); | ||
35 | return array($error); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * When plugin parameters are saved, we regenerate the custom CSS file with provided settings. | ||
41 | * | ||
42 | * @param array $data $_POST array | ||
43 | * | ||
44 | * @return array Updated $_POST array | ||
45 | */ | ||
46 | function hook_default_colors_save_plugin_parameters($data) | ||
47 | { | ||
48 | $file = PluginManager::$PLUGINS_PATH . '/default_colors/default_colors.css'; | ||
49 | $template = file_get_contents(PluginManager::$PLUGINS_PATH . '/default_colors/default_colors.css.template'); | ||
50 | $content = ''; | ||
51 | foreach (DEFAULT_COLORS_PLACEHOLDERS as $rule) { | ||
52 | $content .= ! empty($data[$rule]) | ||
53 | ? default_colors_format_css_rule($data, $rule) .';'. PHP_EOL | ||
54 | : ''; | ||
55 | } | ||
56 | |||
57 | if (! empty($content)) { | ||
58 | file_put_contents($file, sprintf($template, $content)); | ||
59 | } | ||
60 | |||
61 | return $data; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * When linklist is displayed, include default_colors CSS file. | ||
66 | * | ||
67 | * @param array $data - header data. | ||
68 | * | ||
69 | * @return mixed - header data with default_colors CSS file added. | ||
70 | */ | ||
71 | function hook_default_colors_render_includes($data) | ||
72 | { | ||
73 | $file = PluginManager::$PLUGINS_PATH . '/default_colors/default_colors.css'; | ||
74 | if (file_exists($file )) { | ||
75 | $data['css_files'][] = $file ; | ||
76 | } | ||
77 | |||
78 | return $data; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * Create a valid CSS rule from parameters settings and plugin parameter. | ||
83 | * | ||
84 | * @param array $data $_POST array | ||
85 | * @param string $parameter Plugin parameter name | ||
86 | * | ||
87 | * @return string CSS rules for the provided parameter and its matching value. | ||
88 | */ | ||
89 | function default_colors_format_css_rule($data, $parameter) | ||
90 | { | ||
91 | if (empty($data[$parameter])) { | ||
92 | return ''; | ||
93 | } | ||
94 | |||
95 | $key = str_replace('DEFAULT_COLORS_', '', $parameter); | ||
96 | $key = str_replace('_', '-', strtolower($key)) .'-color'; | ||
97 | return ' --'. $key .': '. $data[$parameter]; | ||
98 | } | ||
99 | |||
100 | |||
101 | /** | ||
102 | * This function is never called, but contains translation calls for GNU gettext extraction. | ||
103 | */ | ||
104 | function default_colors_translation() | ||
105 | { | ||
106 | // meta | ||
107 | t('Override default theme colors. Use any CSS valid color.'); | ||
108 | t('Main color (navbar green)'); | ||
109 | t('Background color (light grey)'); | ||
110 | t('Dark main color (e.g. visited links)'); | ||
111 | } | ||
diff --git a/plugins/demo_plugin/demo_plugin.meta b/plugins/demo_plugin/demo_plugin.meta index b063ecb7..cd616441 100644 --- a/plugins/demo_plugin/demo_plugin.meta +++ b/plugins/demo_plugin/demo_plugin.meta | |||
@@ -1 +1,4 @@ | |||
1 | description="A demo plugin covering all use cases for template designers and plugin developers." | 1 | description="A demo plugin covering all use cases for template designers and plugin developers." |
2 | parameters="DEMO_PLUGIN_PARAMETER;DEMO_PLUGIN_OTHER_PARAMETER" | ||
3 | parameter.DEMO_PLUGIN_PARAMETER="This is a parameter dedicated to the demo plugin. It'll be suffixed." | ||
4 | parameter.DEMO_PLUGIN_OTHER_PARAMETER="Other demo parameter" | ||
diff --git a/plugins/demo_plugin/demo_plugin.php b/plugins/demo_plugin/demo_plugin.php index 95ea7fe2..71ba7495 100644 --- a/plugins/demo_plugin/demo_plugin.php +++ b/plugins/demo_plugin/demo_plugin.php | |||
@@ -457,10 +457,29 @@ function hook_demo_plugin_render_feed($data) | |||
457 | } | 457 | } |
458 | 458 | ||
459 | /** | 459 | /** |
460 | * When plugin parameters are saved. | ||
461 | * | ||
462 | * @param array $data $_POST array | ||
463 | * | ||
464 | * @return array Updated $_POST array | ||
465 | */ | ||
466 | function hook_demo_plugin_save_plugin_parameters($data) | ||
467 | { | ||
468 | // Here we edit the provided value, but we can use this to generate config files, etc. | ||
469 | if (! empty($data['DEMO_PLUGIN_PARAMETER']) && ! endsWith($data['DEMO_PLUGIN_PARAMETER'], '_SUFFIX')) { | ||
470 | $data['DEMO_PLUGIN_PARAMETER'] .= '_SUFFIX'; | ||
471 | } | ||
472 | |||
473 | return $data; | ||
474 | } | ||
475 | |||
476 | /** | ||
460 | * This function is never called, but contains translation calls for GNU gettext extraction. | 477 | * This function is never called, but contains translation calls for GNU gettext extraction. |
461 | */ | 478 | */ |
462 | function demo_dummy_translation() | 479 | function demo_dummy_translation() |
463 | { | 480 | { |
464 | // meta | 481 | // meta |
465 | t('A demo plugin covering all use cases for template designers and plugin developers.'); | 482 | t('A demo plugin covering all use cases for template designers and plugin developers.'); |
483 | t('This is a parameter dedicated to the demo plugin. It\'ll be suffixed.'); | ||
484 | t('Other demo parameter'); | ||
466 | } | 485 | } |
diff --git a/tests/plugins/PluginDefaultColorsTest.php b/tests/plugins/PluginDefaultColorsTest.php new file mode 100644 index 00000000..b9951cca --- /dev/null +++ b/tests/plugins/PluginDefaultColorsTest.php | |||
@@ -0,0 +1,195 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Shaarli\Plugin\DefaultColors; | ||
4 | |||
5 | use DateTime; | ||
6 | use PHPUnit\Framework\TestCase; | ||
7 | use Shaarli\Bookmark\LinkDB; | ||
8 | use Shaarli\Config\ConfigManager; | ||
9 | use Shaarli\Plugin\PluginManager; | ||
10 | |||
11 | require_once 'plugins/default_colors/default_colors.php'; | ||
12 | |||
13 | /** | ||
14 | * Class PluginDefaultColorsTest | ||
15 | * | ||
16 | * Test the DefaultColors plugin (allowing to override default template colors). | ||
17 | */ | ||
18 | class PluginDefaultColorsTest extends TestCase | ||
19 | { | ||
20 | /** | ||
21 | * Reset plugin path | ||
22 | */ | ||
23 | public function setUp() | ||
24 | { | ||
25 | PluginManager::$PLUGINS_PATH = 'sandbox'; | ||
26 | mkdir(PluginManager::$PLUGINS_PATH . '/default_colors/'); | ||
27 | copy( | ||
28 | 'plugins/default_colors/default_colors.css.template', | ||
29 | PluginManager::$PLUGINS_PATH . '/default_colors/default_colors.css.template' | ||
30 | ); | ||
31 | } | ||
32 | |||
33 | /** | ||
34 | * Remove sandbox files and folder | ||
35 | */ | ||
36 | public function tearDown() | ||
37 | { | ||
38 | if (file_exists('sandbox/default_colors/default_colors.css.template')) { | ||
39 | unlink('sandbox/default_colors/default_colors.css.template'); | ||
40 | } | ||
41 | |||
42 | if (file_exists('sandbox/default_colors/default_colors.css')) { | ||
43 | unlink('sandbox/default_colors/default_colors.css'); | ||
44 | } | ||
45 | |||
46 | if (is_dir('sandbox/default_colors')) { | ||
47 | rmdir('sandbox/default_colors'); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Test DefaultColors init without errors. | ||
53 | */ | ||
54 | public function testDefaultColorsInitNoError() | ||
55 | { | ||
56 | $conf = new ConfigManager(''); | ||
57 | $conf->set('plugins.DEFAULT_COLORS_BACKGROUND', 'value'); | ||
58 | $errors = default_colors_init($conf); | ||
59 | $this->assertEmpty($errors); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Test DefaultColors init with errors. | ||
64 | */ | ||
65 | public function testDefaultColorsInitError() | ||
66 | { | ||
67 | $conf = new ConfigManager(''); | ||
68 | $errors = default_colors_init($conf); | ||
69 | $this->assertNotEmpty($errors); | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * Test the save plugin parameters hook with all colors specified. | ||
74 | */ | ||
75 | public function testSavePluginParametersAll() | ||
76 | { | ||
77 | $post = [ | ||
78 | 'other1' => true, | ||
79 | 'DEFAULT_COLORS_MAIN' => 'blue', | ||
80 | 'DEFAULT_COLORS_BACKGROUND' => 'pink', | ||
81 | 'other2' => ['yep'], | ||
82 | 'DEFAULT_COLORS_DARK_MAIN' => 'green', | ||
83 | ]; | ||
84 | |||
85 | hook_default_colors_save_plugin_parameters($post); | ||
86 | $this->assertFileExists($file = 'sandbox/default_colors/default_colors.css'); | ||
87 | $content = file_get_contents($file); | ||
88 | $expected = ':root { | ||
89 | --main-color: blue; | ||
90 | --background-color: pink; | ||
91 | --dark-main-color: green; | ||
92 | |||
93 | } | ||
94 | '; | ||
95 | $this->assertEquals($expected, $content); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Test the save plugin parameters hook with only one color specified. | ||
100 | */ | ||
101 | public function testSavePluginParametersSingle() | ||
102 | { | ||
103 | $post = [ | ||
104 | 'other1' => true, | ||
105 | 'DEFAULT_COLORS_BACKGROUND' => 'pink', | ||
106 | 'other2' => ['yep'], | ||
107 | 'DEFAULT_COLORS_DARK_MAIN' => '', | ||
108 | ]; | ||
109 | |||
110 | hook_default_colors_save_plugin_parameters($post); | ||
111 | $this->assertFileExists($file = 'sandbox/default_colors/default_colors.css'); | ||
112 | $content = file_get_contents($file); | ||
113 | $expected = ':root { | ||
114 | --background-color: pink; | ||
115 | |||
116 | } | ||
117 | '; | ||
118 | $this->assertEquals($expected, $content); | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Test the save plugin parameters hook with no color specified. | ||
123 | */ | ||
124 | public function testSavePluginParametersNone() | ||
125 | { | ||
126 | hook_default_colors_save_plugin_parameters([]); | ||
127 | $this->assertFileNotExists($file = 'sandbox/default_colors/default_colors.css'); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Make sure that the CSS is properly included by the include hook. | ||
132 | */ | ||
133 | public function testIncludeWithFile() | ||
134 | { | ||
135 | $data = [ | ||
136 | 'css_files' => ['file1'], | ||
137 | 'js_files' => ['file2'], | ||
138 | ]; | ||
139 | touch($file = 'sandbox/default_colors/default_colors.css'); | ||
140 | $processedData = hook_default_colors_render_includes($data); | ||
141 | |||
142 | $this->assertCount(2, $processedData['css_files']); | ||
143 | $this->assertEquals($file, $processedData['css_files'][1]); | ||
144 | $this->assertCount(1, $processedData['js_files']); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * Make sure that the CSS is not included by the include hook if the CSS file does not exist. | ||
149 | */ | ||
150 | public function testIncludeWithoutFile() | ||
151 | { | ||
152 | $data = [ | ||
153 | 'css_files' => ['file1'], | ||
154 | 'js_files' => ['file2'], | ||
155 | ]; | ||
156 | $processedData = hook_default_colors_render_includes($data); | ||
157 | |||
158 | $this->assertEquals($data, $processedData); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * Test helper function which generates CSS rules with valid input. | ||
163 | */ | ||
164 | public function testFormatCssRuleValid() | ||
165 | { | ||
166 | $data = [ | ||
167 | 'other1' => true, | ||
168 | 'DEFAULT_COLORS_BLIP_BLOP' => 'shinyColor', | ||
169 | 'other2' => ['yep'], | ||
170 | ]; | ||
171 | $result = default_colors_format_css_rule($data, 'DEFAULT_COLORS_BLIP_BLOP'); | ||
172 | $this->assertEquals(' --blip-blop-color: shinyColor', $result); | ||
173 | |||
174 | $data = ['unknown-parameter' => true]; | ||
175 | $result = default_colors_format_css_rule($data, 'unknown-parameter'); | ||
176 | $this->assertEquals(' --unknown-parameter-color: 1', $result); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Test helper function which generates CSS rules with invalid input. | ||
181 | */ | ||
182 | public function testFormatCssRuleInvalid() | ||
183 | { | ||
184 | $result = default_colors_format_css_rule([], 'DEFAULT_COLORS_BLIP_BLOP'); | ||
185 | $this->assertEmpty($result); | ||
186 | |||
187 | $data = [ | ||
188 | 'other1' => true, | ||
189 | 'DEFAULT_COLORS_BLIP_BLOP' => 'shinyColor', | ||
190 | 'other2' => ['yep'], | ||
191 | ]; | ||
192 | $result = default_colors_format_css_rule($data, ''); | ||
193 | $this->assertEmpty($result); | ||
194 | } | ||
195 | } | ||