]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
New basePath: fix officiel plugin paths and vintage template
authorArthurHoaro <arthur@hoa.ro>
Sun, 26 Jul 2020 12:43:10 +0000 (14:43 +0200)
committerArthurHoaro <arthur@hoa.ro>
Sun, 26 Jul 2020 12:43:10 +0000 (14:43 +0200)
39 files changed:
application/config/ConfigPlugin.php
application/front/ShaarliMiddleware.php
application/front/controller/admin/ManageShaareController.php
application/front/controller/admin/PluginsController.php
application/front/controller/admin/ToolsController.php
application/front/controller/visitor/BookmarkListController.php
application/front/controller/visitor/DailyController.php
application/front/controller/visitor/FeedController.php
application/front/controller/visitor/PictureWallController.php
application/front/controller/visitor/ShaarliVisitorController.php
application/front/controller/visitor/TagCloudController.php
application/plugin/PluginManager.php
application/render/PageBuilder.php
plugins/addlink_toolbar/addlink_toolbar.php
plugins/archiveorg/archiveorg.html
plugins/archiveorg/archiveorg.php
plugins/demo_plugin/demo_plugin.php
plugins/isso/isso_button.html [deleted file]
plugins/qrcode/qrcode.php
plugins/qrcode/shaarli-qrcode.js
plugins/wallabag/wallabag.php
tests/config/ConfigPluginTest.php
tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php
tests/front/controller/admin/PluginsControllerTest.php
tests/front/controller/admin/SessionFilterControllerTest.php
tests/front/controller/visitor/ShaarliVisitorControllerTest.php
tests/plugins/PluginAddlinkTest.php
tpl/vintage/changepassword.html
tpl/vintage/changetag.html
tpl/vintage/configure.html
tpl/vintage/editlink.html
tpl/vintage/export.html
tpl/vintage/includes.html
tpl/vintage/install.html
tpl/vintage/linklist.html
tpl/vintage/loginform.html
tpl/vintage/page.footer.html
tpl/vintage/pluginsadmin.html
tpl/vintage/thumbnails.html

index dbb249374a7262053b5e03000d38b746c9772563..ea8dfbdade4f0f0776eff517545e1b3f96f536f3 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 use Shaarli\Config\Exception\PluginConfigOrderException;
+use Shaarli\Plugin\PluginManager;
 
 /**
  * Plugin configuration helper functions.
@@ -19,6 +20,20 @@ use Shaarli\Config\Exception\PluginConfigOrderException;
  */
 function save_plugin_config($formData)
 {
+    // We can only save existing plugins
+    $directories = str_replace(
+        PluginManager::$PLUGINS_PATH . '/',
+        '',
+        glob(PluginManager::$PLUGINS_PATH . '/*')
+    );
+    $formData = array_filter(
+        $formData,
+        function ($value, string $key) use ($directories) {
+            return startsWith($key, 'order') || in_array($key, $directories);
+        },
+        ARRAY_FILTER_USE_BOTH
+    );
+
     // Make sure there are no duplicates in orders.
     if (!validate_plugin_order($formData)) {
         throw new PluginConfigOrderException();
@@ -69,7 +84,7 @@ function validate_plugin_order($formData)
     $orders = array();
     foreach ($formData as $key => $value) {
         // No duplicate order allowed.
-        if (in_array($value, $orders)) {
+        if (in_array($value, $orders, true)) {
             return false;
         }
 
index fd978e997eea34b1a4d23b6452450bfff19fe8e4..92c0e911b76a5fdf4bef2438a44670fc3f2b96a1 100644 (file)
@@ -60,7 +60,7 @@ class ShaarliMiddleware
 
             $response = $response->withStatus($e->getCode());
 
-            return $response->write($this->container->pageBuilder->render('error'));
+            return $response->write($this->container->pageBuilder->render('error', $this->container->basePath));
         } catch (UnauthorizedException $e) {
             $returnUrl = urlencode($this->container->environment['REQUEST_URI']);
 
@@ -80,7 +80,7 @@ class ShaarliMiddleware
 
             $response = $response->withStatus(500);
 
-            return $response->write($this->container->pageBuilder->render('error'));
+            return $response->write($this->container->pageBuilder->render('error', $this->container->basePath));
         }
     }
 
index 3aa484239e71b62539157e20ba7b9f70b15e543c..33e1188ef73a6f0df55c2daba25e88cea29d8f91 100644 (file)
@@ -152,7 +152,7 @@ class ManageShaareController extends ShaarliAdminController
         // To preserve backward compatibility with 3rd parties, plugins still use arrays
         $formatter = $this->container->formatterFactory->getFormatter('raw');
         $data = $formatter->format($bookmark);
-        $data = $this->executeHooks('save_link', $data);
+        $this->executePageHooks('save_link', $data);
 
         $bookmark->fromArray($data);
         $this->container->bookmarkService->set($bookmark);
@@ -211,7 +211,7 @@ class ManageShaareController extends ShaarliAdminController
             }
 
             $data = $formatter->format($bookmark);
-            $this->container->pluginManager->executeHooks('delete_link', $data);
+            $this->executePageHooks('delete_link', $data);
             $this->container->bookmarkService->remove($bookmark, false);
             ++ $count;
         }
@@ -283,7 +283,7 @@ class ManageShaareController extends ShaarliAdminController
 
             // To preserve backward compatibility with 3rd parties, plugins still use arrays
             $data = $formatter->format($bookmark);
-            $this->container->pluginManager->executeHooks('save_link', $data);
+            $this->executePageHooks('save_link', $data);
             $bookmark->fromArray($data);
 
             $this->container->bookmarkService->set($bookmark, false);
@@ -325,7 +325,7 @@ class ManageShaareController extends ShaarliAdminController
 
         // To preserve backward compatibility with 3rd parties, plugins still use arrays
         $data = $formatter->format($bookmark);
-        $this->container->pluginManager->executeHooks('save_link', $data);
+        $this->executePageHooks('save_link', $data);
         $bookmark->fromArray($data);
 
         $this->container->bookmarkService->set($bookmark);
@@ -354,7 +354,7 @@ class ManageShaareController extends ShaarliAdminController
             'default_private_links' => $this->container->conf->get('privacy.default_private_links', false),
         ];
 
-        $data = $this->executeHooks('render_editlink', $data);
+        $this->executePageHooks('render_editlink', $data, TemplatePage::EDIT_LINK);
 
         foreach ($data as $key => $value) {
             $this->assignView($key, $value);
@@ -368,19 +368,4 @@ class ManageShaareController extends ShaarliAdminController
 
         return $response->write($this->render(TemplatePage::EDIT_LINK));
     }
-
-    /**
-     * @param mixed[] $data Variables passed to the template engine
-     *
-     * @return mixed[] Template data after active plugins render_picwall hook execution.
-     */
-    protected function executeHooks(string $hook, array $data): array
-    {
-        $this->container->pluginManager->executeHooks(
-            $hook,
-            $data
-        );
-
-        return $data;
-    }
 }
index 1eb7e6357a346dd7e889c0ba4b89ff0c58994102..0e09116e98ddb4ca334455c1db2d69d3b5d3eb69 100644 (file)
@@ -58,7 +58,7 @@ class PluginsController extends ShaarliAdminController
         try {
             $parameters = $request->getParams() ?? [];
 
-            $this->executeHooks($parameters);
+            $this->executePageHooks('save_plugin_parameters', $parameters);
 
             if (isset($parameters['parameters_form'])) {
                 unset($parameters['parameters_form']);
@@ -81,19 +81,4 @@ class PluginsController extends ShaarliAdminController
 
         return $this->redirect($response, '/admin/plugins');
     }
-
-    /**
-     * @param mixed[] $data Variables passed to the template engine
-     *
-     * @return mixed[] Template data after active plugins render_picwall hook execution.
-     */
-    protected function executeHooks(array $data): array
-    {
-        $this->container->pluginManager->executeHooks(
-            'save_plugin_parameters',
-            $data
-        );
-
-        return $data;
-    }
 }
index a476e8983a4051748015e8ea5e44fb7ff5d15f8e..a87f20d29f9d18a443cd066a7f434a60fc61e9b3 100644 (file)
@@ -22,7 +22,7 @@ class ToolsController extends ShaarliAdminController
             'sslenabled' => is_https($this->container->environment),
         ];
 
-        $data = $this->executeHooks($data);
+        $this->executePageHooks('render_tools', $data, TemplatePage::TOOLS);
 
         foreach ($data as $key => $value) {
             $this->assignView($key, $value);
@@ -32,19 +32,4 @@ class ToolsController extends ShaarliAdminController
 
         return $response->write($this->render(TemplatePage::TOOLS));
     }
-
-    /**
-     * @param mixed[] $data Variables passed to the template engine
-     *
-     * @return mixed[] Template data after active plugins render_picwall hook execution.
-     */
-    protected function executeHooks(array $data): array
-    {
-        $this->container->pluginManager->executeHooks(
-            'render_tools',
-            $data
-        );
-
-        return $data;
-    }
 }
index a37a7f6b09f30c30cf42f6a3e451a0f88ce15fd4..23c4fbaea62e8b17e9855a63a979e89737d33a22 100644 (file)
@@ -124,7 +124,7 @@ class BookmarkListController extends ShaarliVisitorController
 
         $data['pagetitle'] = ($data['pagetitle'] ?? '') . $this->container->conf->get('general.title', 'Shaarli');
 
-        $this->executeHooks($data);
+        $this->executePageHooks('render_linklist', $data, TemplatePage::LINKLIST);
         $this->assignAllView($data);
 
         return $response->write($this->render(TemplatePage::LINKLIST));
@@ -153,7 +153,7 @@ class BookmarkListController extends ShaarliVisitorController
             ]
         );
 
-        $this->executeHooks($data);
+        $this->executePageHooks('render_linklist', $data, TemplatePage::LINKLIST);
         $this->assignAllView($data);
 
         return $response->write($this->render(TemplatePage::LINKLIST));
@@ -182,18 +182,6 @@ class BookmarkListController extends ShaarliVisitorController
         return false;
     }
 
-    /**
-     * @param mixed[] $data Template vars to process in plugins, passed as reference.
-     */
-    protected function executeHooks(array &$data): void
-    {
-        $this->container->pluginManager->executeHooks(
-            'render_linklist',
-            $data,
-            ['loggedin' => $this->container->loginManager->isLoggedIn()]
-        );
-    }
-
     /**
      * @return string[] Default template variables without values.
      */
index 05b4f095970dc4dc19770d28278568561f73855e..808ca5f7ba0a97c318895c9f4b198235a2864149 100644 (file)
@@ -72,13 +72,11 @@ class DailyController extends ShaarliVisitorController
         ];
 
         // Hooks are called before column construction so that plugins don't have to deal with columns.
-        $data = $this->executeHooks($data);
+        $this->executePageHooks('render_daily', $data, TemplatePage::DAILY);
 
         $data['cols'] = $this->calculateColumns($data['linksToDisplay']);
 
-        foreach ($data as $key => $value) {
-            $this->assignView($key, $value);
-        }
+        $this->assignAllView($data);
 
         $mainTitle = $this->container->conf->get('general.title', 'Shaarli');
         $this->assignView(
@@ -190,20 +188,4 @@ class DailyController extends ShaarliVisitorController
 
         return $columns;
     }
-
-    /**
-     * @param mixed[] $data Variables passed to the template engine
-     *
-     * @return mixed[] Template data after active plugins render_picwall hook execution.
-     */
-    protected function executeHooks(array $data): array
-    {
-        $this->container->pluginManager->executeHooks(
-            'render_daily',
-            $data,
-            ['loggedin' => $this->container->loginManager->isLoggedIn()]
-        );
-
-        return $data;
-    }
 }
index f76f55fdf76cc5ff0f3a9a6ca30f3e1f1a30d1b0..da2848c2b0151b115d5d3427236a7f039c96265b 100644 (file)
@@ -46,7 +46,7 @@ class FeedController extends ShaarliVisitorController
 
         $data = $this->container->feedBuilder->buildData($feedType, $request->getParams());
 
-        $data = $this->executeHooks($data, $feedType);
+        $this->executePageHooks('render_feed', $data, $feedType);
         $this->assignAllView($data);
 
         $content = $this->render('feed.'. $feedType);
@@ -55,23 +55,4 @@ class FeedController extends ShaarliVisitorController
 
         return $response->write($content);
     }
-
-    /**
-     * @param mixed[] $data Template data
-     *
-     * @return mixed[] Template data after active plugins hook execution.
-     */
-    protected function executeHooks(array $data, string $feedType): array
-    {
-        $this->container->pluginManager->executeHooks(
-            'render_feed',
-            $data,
-            [
-                'loggedin' => $this->container->loginManager->isLoggedIn(),
-                'target' => $feedType,
-            ]
-        );
-
-        return $data;
-    }
 }
index 5ef2cb1714c68e0e9edb26dfa861985386ebac49..3c57f8dd61869787565703ad492fb764dd0b5a67 100644 (file)
@@ -42,30 +42,13 @@ class PictureWallController extends ShaarliVisitorController
             }
         }
 
-        $data = $this->executeHooks($linksToDisplay);
+        $data = ['linksToDisplay' => $linksToDisplay];
+        $this->executePageHooks('render_picwall', $data, TemplatePage::PICTURE_WALL);
+
         foreach ($data as $key => $value) {
             $this->assignView($key, $value);
         }
 
         return $response->write($this->render(TemplatePage::PICTURE_WALL));
     }
-
-    /**
-     * @param mixed[] $linksToDisplay List of formatted bookmarks
-     *
-     * @return mixed[] Template data after active plugins render_picwall hook execution.
-     */
-    protected function executeHooks(array $linksToDisplay): array
-    {
-        $data = [
-            'linksToDisplay' => $linksToDisplay,
-        ];
-        $this->container->pluginManager->executeHooks(
-            'render_picwall',
-            $data,
-            ['loggedin' => $this->container->loginManager->isLoggedIn()]
-        );
-
-        return $data;
-    }
 }
index b494a8e6bed3587a1edf66ebe921e7bc2b89cf97..47057d97664920a08e25af6590491a3f2cbaa7a3 100644 (file)
@@ -60,22 +60,9 @@ abstract class ShaarliVisitorController
         $this->assignView('privateLinkcount', $this->container->bookmarkService->count(BookmarkFilter::$PRIVATE));
         $this->assignView('plugin_errors', $this->container->pluginManager->getErrors());
 
-        /*
-         * Define base path (if Shaarli is installed in a domain's subfolder, e.g. `/shaarli`)
-         * and the asset path (subfolder/tpl/default for default theme).
-         * These MUST be used to create an internal link or to include an asset in templates.
-         */
-        $this->assignView('base_path', $this->container->basePath);
-        $this->assignView(
-            'asset_path',
-            $this->container->basePath . '/' .
-            rtrim($this->container->conf->get('resource.raintpl_tpl', 'tpl'), '/') . '/' .
-            $this->container->conf->get('resource.theme', 'default')
-        );
-
         $this->executeDefaultHooks($template);
 
-        return $this->container->pageBuilder->render($template);
+        return $this->container->pageBuilder->render($template, $this->container->basePath);
     }
 
     /**
@@ -97,13 +84,29 @@ abstract class ShaarliVisitorController
                 $pluginData,
                 [
                     'target' => $template,
-                    'loggedin' => $this->container->loginManager->isLoggedIn()
+                    'loggedin' => $this->container->loginManager->isLoggedIn(),
+                    'basePath' => $this->container->basePath,
                 ]
             );
             $this->assignView('plugins_' . $name, $pluginData);
         }
     }
 
+    protected function executePageHooks(string $hook, array &$data, string $template = null): void
+    {
+        $params = [
+            'target' => $template,
+            'loggedin' => $this->container->loginManager->isLoggedIn(),
+            'basePath' => $this->container->basePath,
+        ];
+
+        $this->container->pluginManager->executeHooks(
+            $hook,
+            $data,
+            $params
+        );
+    }
+
     /**
      * Simple helper which prepend the base path to redirect path.
      *
index 15b6d7b78b65565c2b166bb30635cbe80d4227fa..f9c529bcc4fbeab904227c02a4a6f9d673c24898 100644 (file)
@@ -71,10 +71,8 @@ class TagCloudController extends ShaarliVisitorController
             'search_tags' => $searchTags,
             'tags' => $tags,
         ];
-        $data = $this->executeHooks('tag' . $type, $data);
-        foreach ($data as $key => $value) {
-            $this->assignView($key, $value);
-        }
+        $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type);
+        $this->assignAllView($data);
 
         $searchTags = !empty($searchTags) ? $searchTags .' - ' : '';
         $this->assignView(
@@ -82,7 +80,7 @@ class TagCloudController extends ShaarliVisitorController
             $searchTags . t('Tag '. $type) .' - '. $this->container->conf->get('general.title', 'Shaarli')
         );
 
-        return $response->write($this->render('tag.'. $type));
+        return $response->write($this->render('tag.' . $type));
     }
 
     /**
@@ -112,20 +110,4 @@ class TagCloudController extends ShaarliVisitorController
 
         return $tagList;
     }
-
-    /**
-     * @param mixed[] $data Template data
-     *
-     * @return mixed[] Template data after active plugins hook execution.
-     */
-    protected function executeHooks(string $template, array $data): array
-    {
-        $this->container->pluginManager->executeHooks(
-            'render_'. $template,
-            $data,
-            ['loggedin' => $this->container->loginManager->isLoggedIn()]
-        );
-
-        return $data;
-    }
 }
index 591a918098ee46a8d22d9643ebabbe7a9f0756b9..b3e8b2f8e28c0ebdd9def9e8d7f8df00c7f4e903 100644 (file)
@@ -108,6 +108,10 @@ class PluginManager
             $data['_LOGGEDIN_'] = $params['loggedin'];
         }
 
+        if (isset($params['basePath'])) {
+            $data['_BASE_PATH_'] = $params['basePath'];
+        }
+
         foreach ($this->loadedPlugins as $plugin) {
             $hookFunction = $this->buildHookName($hook, $plugin);
 
index 471724c00f1f725c65ed5416523f101da04ffbf8..7a7166732392a5726227bd33d769f0dd8abbc96e 100644 (file)
@@ -3,6 +3,7 @@
 namespace Shaarli\Render;
 
 use Exception;
+use exceptions\MissingBasePathException;
 use RainTPL;
 use Shaarli\ApplicationUtils;
 use Shaarli\Bookmark\BookmarkServiceInterface;
@@ -156,7 +157,7 @@ class PageBuilder
      * Affect variable after controller processing.
      * Used for alert messages.
      */
-    protected function finalize(): void
+    protected function finalize(string $basePath): void
     {
         // TODO: use the SessionManager
         $messageKeys = [
@@ -170,6 +171,14 @@ class PageBuilder
                 unset($_SESSION[$messageKey]);
             }
         }
+
+        $this->assign('base_path', $basePath);
+        $this->assign(
+            'asset_path',
+            $basePath . '/' .
+            rtrim($this->conf->get('resource.raintpl_tpl', 'tpl'), '/') . '/' .
+            $this->conf->get('resource.theme', 'default')
+        );
     }
 
     /**
@@ -209,23 +218,6 @@ class PageBuilder
         return true;
     }
 
-    /**
-     * Render a specific page (using a template file).
-     * e.g. $pb->renderPage('picwall');
-     *
-     * @param string $page Template filename (without extension).
-     */
-    public function renderPage($page)
-    {
-        if ($this->tpl === false) {
-            $this->initialize();
-        }
-
-        $this->finalize();
-
-        $this->tpl->draw($page);
-    }
-
     /**
      * Render a specific page as string (using a template file).
      * e.g. $pb->render('picwall');
@@ -234,13 +226,13 @@ class PageBuilder
      *
      * @return string Processed template content
      */
-    public function render(string $page): string
+    public function render(string $page, string $basePath): string
     {
         if ($this->tpl === false) {
             $this->initialize();
         }
 
-        $this->finalize();
+        $this->finalize($basePath);
 
         return $this->tpl->draw($page, true);
     }
index c3e7abaf5388bf4fe557b03a0412a67e3778c782..ab6ed6de0cc34f2eca752ea293c90b1b45655a4b 100644 (file)
@@ -20,7 +20,7 @@ function hook_addlink_toolbar_render_header($data)
         $form = array(
             'attr' => array(
                 'method' => 'GET',
-                'action' => '',
+                'action' => $data['_BASE_PATH_'] . '/admin/shaare',
                 'name'   => 'addform',
                 'class'  => 'addform',
             ),
index ad501f4799b5770b6bd6f77c550c49317ac55bbe..e37d887e85c0ab129fe132c68bdba1725b517611 100644 (file)
@@ -1,5 +1,5 @@
 <span>
   <a href="https://web.archive.org/web/%s">
-    <img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
+    <img class="linklist-plugin-icon" src="%s/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
   </a>
 </span>
index 0ee1c73c9333ef0fd9635db3ededbc64fb44521e..f26e61292cea3c50e44d32e7f7ff408829d9e881 100644 (file)
@@ -17,12 +17,13 @@ use Shaarli\Plugin\PluginManager;
 function hook_archiveorg_render_linklist($data)
 {
     $archive_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/archiveorg/archiveorg.html');
+    $path = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH;
 
     foreach ($data['links'] as &$value) {
         if ($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) {
             continue;
         }
-        $archive = sprintf($archive_html, $value['url'], t('View on archive.org'));
+        $archive = sprintf($archive_html, $value['url'], $path, t('View on archive.org'));
         $value['link_plugin'][] = $archive;
     }
 
index dd73d6a2129acd2be76a612a8b3c379f7e5bcd3f..defb01f7e4457d05f95f0f95e939297300033904 100644 (file)
@@ -118,7 +118,7 @@ function hook_demo_plugin_render_header($data)
         $form = array(
             'attr' => array(
                 'method' => 'GET',
-                'action' => '?',
+                'action' => $data['_BASE_PATH_'] . '/',
                 'class' => 'addform',
             ),
             'inputs' => array(
diff --git a/plugins/isso/isso_button.html b/plugins/isso/isso_button.html
deleted file mode 100644 (file)
index 3f82848..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<span>
-  <a href="?%s#isso-thread">
-    <img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
-  </a>
-</span>
index 2ec0cb6576d859c3723f96d39cd8f9165c8cfd5e..3b5dae344dd63c3b688fc2d40ee8ff2af99e8f09 100644 (file)
@@ -19,11 +19,12 @@ function hook_qrcode_render_linklist($data)
 {
     $qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html');
 
+    $path = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH;
     foreach ($data['links'] as &$value) {
         $qrcode = sprintf(
             $qrcode_html,
             $value['url'],
-            PluginManager::$PLUGINS_PATH
+            $path
         );
         $value['link_plugin'][] = $qrcode;
     }
@@ -41,7 +42,7 @@ function hook_qrcode_render_linklist($data)
 function hook_qrcode_render_footer($data)
 {
     if ($data['_PAGE_'] == TemplatePage::LINKLIST) {
-        $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
+        $data['js_files'][] =  PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
     }
 
     return $data;
index fe77c4cdc47cbb4ae36471513908e950adfe8d6d..3316d6f63d272b2e5b13215e61aae4a27d19e459 100644 (file)
 
 // Show the QR-Code of a permalink (when the QR-Code icon is clicked).
 function showQrCode(caller,loading)
-{ 
+{
     // Dynamic javascript lib loading: We only load qr.js if the QR code icon is clicked:
     if (typeof(qr) == 'undefined') // Load qr.js only if not present.
     {
         if (!loading)  // If javascript lib is still loading, do not append script to body.
         {
-            var element = document.createElement("script");
-            element.src = "plugins/qrcode/qr-1.1.3.min.js";
+          var basePath = document.querySelector('input[name="js_base_path"]').value;
+          var element = document.createElement("script");
+            element.src = basePath + "/plugins/qrcode/qr-1.1.3.min.js";
             document.body.appendChild(element);
         }
         setTimeout(function() { showQrCode(caller,true);}, 200); // Retry in 200 milliseconds.
@@ -44,7 +45,7 @@ function showQrCode(caller,loading)
 
     // Remove previous qrcode if present.
     removeQrcode();
-    
+
     // Build the div which contains the QR-Code:
     var element = document.createElement('div');
     element.id = 'permalinkQrcode';
@@ -57,11 +58,11 @@ function showQrCode(caller,loading)
         // Damn IE
         element.setAttribute('onclick', 'this.parentNode.removeChild(this);' );
     }
-    
+
     // Build the QR-Code:
     var image = qr.image({size: 8,value: caller.dataset.permalink});
     if (image)
-    { 
+    {
         element.appendChild(image);
         element.innerHTML += "<br>Click to close";
         caller.parentNode.appendChild(element);
@@ -87,4 +88,4 @@ function removeQrcode()
         elem.parentNode.removeChild(elem);
     }
     return false;
-}
\ No newline at end of file
+}
index bc35df08dcde122f0ca11e8fad30dc17e6f16baf..805c1ad986aa9bc4c37b2531ca521f891e6cffd6 100644 (file)
@@ -45,12 +45,14 @@ function hook_wallabag_render_linklist($data, $conf)
     $wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html');
 
     $linkTitle = t('Save to wallabag');
+    $path = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH;
+
     foreach ($data['links'] as &$value) {
         $wallabag = sprintf(
             $wallabagHtml,
             $wallabagInstance->getWallabagUrl(),
             urlencode($value['url']),
-            PluginManager::$PLUGINS_PATH,
+            $path,
             $linkTitle
         );
         $value['link_plugin'][] = $wallabag;
index d7a70e6886b54a889eed845560350eae05cefabe..b2cc00455284b8fe339caae0bd02b31f8f1ec696 100644 (file)
@@ -2,6 +2,7 @@
 namespace Shaarli\Config;
 
 use Shaarli\Config\Exception\PluginConfigOrderException;
+use Shaarli\Plugin\PluginManager;
 
 require_once 'application/config/ConfigPlugin.php';
 
@@ -17,23 +18,30 @@ class ConfigPluginTest extends \PHPUnit\Framework\TestCase
      */
     public function testSavePluginConfigValid()
     {
-        $data = array(
+        $data = [
             'order_plugin1' => 2,   // no plugin related
             'plugin2' => 0,         // new - at the end
             'plugin3' => 0,         // 2nd
             'order_plugin3' => 8,
             'plugin4' => 0,         // 1st
             'order_plugin4' => 5,
-        );
+        ];
 
-        $expected = array(
+        $expected = [
             'plugin3',
             'plugin4',
             'plugin2',
-        );
+        ];
+
+        mkdir($path = __DIR__ . '/folder');
+        PluginManager::$PLUGINS_PATH = $path;
+        array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, $expected);
 
         $out = save_plugin_config($data);
         $this->assertEquals($expected, $out);
+
+        array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, $expected);
+        rmdir($path);
     }
 
     /**
index caaf549d135fed24b657fb64d741467e9348437b..dee622bba829104be8ade4486dce594b1e4eb39a 100644 (file)
@@ -59,8 +59,12 @@ class DeleteBookmarkTest extends TestCase
             ->with('raw')
             ->willReturnCallback(function () use ($bookmark): BookmarkFormatter {
                 $formatter = $this->createMock(BookmarkFormatter::class);
-
-                $formatter->expects(static::once())->method('format')->with($bookmark);
+                $formatter
+                    ->expects(static::once())
+                    ->method('format')
+                    ->with($bookmark)
+                    ->willReturn(['formatted' => $bookmark])
+                ;
 
                 return $formatter;
             })
@@ -70,7 +74,7 @@ class DeleteBookmarkTest extends TestCase
         $this->container->pluginManager
             ->expects(static::once())
             ->method('executeHooks')
-            ->with('delete_link')
+            ->with('delete_link', ['formatted' => $bookmark])
         ;
 
         $result = $this->controller->deleteBookmark($request, $response);
@@ -129,6 +133,9 @@ class DeleteBookmarkTest extends TestCase
                     ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
                         return [$bookmark];
                     }, $bookmarks))
+                    ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
+                        return ['formatted' => $bookmark];
+                    }, $bookmarks))
                 ;
 
                 return $formatter;
@@ -254,6 +261,9 @@ class DeleteBookmarkTest extends TestCase
                     ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
                         return [$bookmark];
                     }, $bookmarks))
+                    ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
+                        return ['formatted' => $bookmark];
+                    }, $bookmarks))
                 ;
 
                 return $formatter;
@@ -350,7 +360,12 @@ class DeleteBookmarkTest extends TestCase
         $this->container->formatterFactory
             ->expects(static::once())
             ->method('getFormatter')
-            ->willReturn($this->createMock(BookmarkFormatter::class))
+            ->willReturnCallback(function (): BookmarkFormatter {
+                $formatter = $this->createMock(BookmarkFormatter::class);
+                $formatter->method('format')->willReturn(['formatted']);
+
+                return $formatter;
+            })
         ;
 
         $result = $this->controller->deleteBookmark($request, $response);
index ad0cda70ad501d7a513eff2c9eddac812e6f013e..5b59285c9916486bdb5719f54c69fcfb94332127 100644 (file)
@@ -7,6 +7,7 @@ namespace Shaarli\Front\Controller\Admin;
 use PHPUnit\Framework\TestCase;
 use Shaarli\Config\ConfigManager;
 use Shaarli\Front\Exception\WrongTokenException;
+use Shaarli\Plugin\PluginManager;
 use Shaarli\Security\SessionManager;
 use Slim\Http\Request;
 use Slim\Http\Response;
@@ -15,6 +16,8 @@ class PluginsControllerTest extends TestCase
 {
     use FrontAdminControllerMockHelper;
 
+    const PLUGIN_NAMES = ['plugin1', 'plugin2', 'plugin3', 'plugin4'];
+
     /** @var PluginsController */
     protected $controller;
 
@@ -23,6 +26,17 @@ class PluginsControllerTest extends TestCase
         $this->createContainer();
 
         $this->controller = new PluginsController($this->container);
+
+        mkdir($path = __DIR__ . '/folder');
+        PluginManager::$PLUGINS_PATH = $path;
+        array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
+    }
+
+    public function tearDown()
+    {
+        $path = __DIR__ . '/folder';
+        array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
+        rmdir($path);
     }
 
     /**
index 124b0bf22d355e752bb6333f3fa018b9701b8efe..7d5511edff6f56db5d1ac3a0283919879fcc5626 100644 (file)
@@ -23,7 +23,7 @@ class SessionFilterControllerTest extends TestCase
 
         $this->controller = new SessionFilterController($this->container);
     }
-    
+
     /**
      * Visibility - Default call for private filter while logged in without current value
      */
index 83d0835850a664f893997e4ea9b1d502ae4e3f5c..316ce49c021114d667d16d3a84942adf629d18ab 100644 (file)
@@ -96,8 +96,6 @@ class ShaarliVisitorControllerTest extends TestCase
         static::assertSame(10, $this->assignedValues['linkcount']);
         static::assertSame(5, $this->assignedValues['privateLinkcount']);
         static::assertSame(['error'], $this->assignedValues['plugin_errors']);
-        static::assertSame('/subfolder', $this->assignedValues['base_path']);
-        static::assertSame('/subfolder/tpl/default', $this->assignedValues['asset_path']);
 
         static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']);
         static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']);
index 4018c1a852bea4c5ca634ce56dbba59cce744c4a..aa5c6988f639da5c9e8097897bdf151fa0b1b960 100644 (file)
@@ -28,6 +28,7 @@ class PluginAddlinkTest extends \PHPUnit\Framework\TestCase
         $data = array($str => $str);
         $data['_PAGE_'] = TemplatePage::LINKLIST;
         $data['_LOGGEDIN_'] = true;
+        $data['_BASE_PATH_'] = '/subfolder';
 
         $data = hook_addlink_toolbar_render_header($data);
         $this->assertEquals($str, $data[$str]);
@@ -36,6 +37,8 @@ class PluginAddlinkTest extends \PHPUnit\Framework\TestCase
         $data = array($str => $str);
         $data['_PAGE_'] = $str;
         $data['_LOGGEDIN_'] = true;
+        $data['_BASE_PATH_'] = '/subfolder';
+
         $data = hook_addlink_toolbar_render_header($data);
         $this->assertEquals($str, $data[$str]);
         $this->assertArrayNotHasKey('fields_toolbar', $data);
@@ -50,6 +53,7 @@ class PluginAddlinkTest extends \PHPUnit\Framework\TestCase
         $data = array($str => $str);
         $data['_PAGE_'] = TemplatePage::LINKLIST;
         $data['_LOGGEDIN_'] = false;
+        $data['_BASE_PATH_'] = '/subfolder';
 
         $data = hook_addlink_toolbar_render_header($data);
         $this->assertEquals($str, $data[$str]);
index c40daf9d385b781fe3c2c1bbfa713b00a2164ba9..7e37b9a3459b7e4f8b6e862cfbe1491be88dcb36 100644 (file)
@@ -4,7 +4,7 @@
 <body onload="document.changepasswordform.oldpassword.focus();">
 <div id="pageheader">
        {include="page.header"}
-       <form method="POST" action="#" name="changepasswordform" id="changepasswordform">
+       <form method="POST" action="{$base_path}/admin/password" name="changepasswordform" id="changepasswordform">
        Old password: <input type="password" name="oldpassword">&nbsp; &nbsp;
        New password: <input type="password" name="setpassword">
        <input type="hidden" name="token" value="{$token}">
@@ -12,4 +12,4 @@
 </div>
 {include="page.footer"}
 </body>
-</html>
\ No newline at end of file
+</html>
index 670a8dd7309c2d73b92927aae72569b434dec351..6ef60252d32394b1b5a5760c9abbacb829e90ec0 100644 (file)
@@ -5,7 +5,7 @@
 <body onload="document.changetag.fromtag.focus();">
 <div id="pageheader">
        {include="page.header"}
-       <form method="POST" action="" name="changetag" id="changetag">
+       <form method="POST" action="{$base_path}/admin/tags" name="changetag" id="changetag">
         <input type="hidden" name="token" value="{$token}">
         <div>
             <label for="fromtag">Tag:</label>
index c5861aaef21ab2f9c7e00d9d16f4c3113239a5c1..ba4f3f71c02fd38e359498a95f09a7d9ae2e3198 100644 (file)
@@ -4,7 +4,7 @@
 <body onload="document.configform.title.focus();">
 <div id="pageheader">
   {include="page.header"}
-  <form method="POST" action="#" name="configform" id="configform">
+  <form method="POST" action="{$base_path}/admin/configure" name="configform" id="configform">
     <input type="hidden" name="token" value="{$token}">
     <table id="configuration_table">
 
index ccf8c6778a0a18f98e05026e5aabe06c9f912fb0..c3671b1f960bf8b2432f13920bc941c63af828a4 100644 (file)
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <html>
 <head>{include="includes"}
-    <link type="text/css" rel="stylesheet" href="inc/awesomplete.css#" />
 </head>
 <body
 {if="$link.title==''"}onload="document.linkform.lf_title.focus();"
@@ -10,9 +9,8 @@
 <div id="pageheader">
     {include="page.header"}
     <div id="shaarli_title"><a href="{$titleLink}">{$shaarlititle}</a></div>
-    {/if}
     <div id="editlinkform">
-        <form method="post" name="linkform">
+        <form method="post" name="linkform" action="{$base_path}/admin/shaare">
             <input type="hidden" name="lf_linkdate" value="{$link.linkdate}">
           {if="isset($link.id)"}
                  <input type="hidden" name="lf_id" value="{$link.id}">
index feee307c8b49a43403ca574b5e9df58825430ea7..c30e3b0ad41f3a3c3dc6944c85fa55a2c8fd64b1 100644 (file)
@@ -10,6 +10,8 @@
         <input type="radio" name="selection" value="all" checked="true"> All<br>
         <input type="radio" name="selection" value="private"> Private<br>
         <input type="radio" name="selection" value="public"> Public<br>
+        <input type="hidden" name="token" value="{$token}">
+
         <br>
         <input type="checkbox" name="prepend_note_url" id="prepend_note_url">
         <label for="prepend_note_url">
index aa2381c6e307710fab555c161c9bfeabf2580614..eac05701c70abf1ed49479faa6dbbd2bf0cfcdcf 100644 (file)
@@ -6,14 +6,14 @@
 <link rel="alternate" type="application/rss+xml" href="{$feedurl}feed/rss?{$searchcrits}#" title="RSS Feed" />
 <link rel="alternate" type="application/atom+xml" href="{$feedurl}feed/atom?{$searchcrits}#" title="ATOM Feed" />
 <link href="img/favicon.ico" rel="shortcut icon" type="image/x-icon" />
-<link type="text/css" rel="stylesheet" href="css/shaarli.min.css" />
+<link type="text/css" rel="stylesheet" href="{$asset_path}/css/shaarli.min.css#" />
 {if="$formatter==='markdown'"}
   <link type="text/css" rel="stylesheet" href="{$asset_path}/css/markdown.min.css?v={$version_hash}#" />
 {/if}
 {loop="$plugins_includes.css_files"}
-<link type="text/css" rel="stylesheet" href="{$value}#"/>
+<link type="text/css" rel="stylesheet" href="{$base_path}/{$value}#"/>
 {/loop}
-{if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if}
+{if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="{$base_path}/data/user.css#" />{/if}
 <link rel="search" type="application/opensearchdescription+xml" href="{$base_path}/open-search#"
       title="Shaarli search - {$shaarlititle|htmlspecialchars}" />
 {if="! empty($links) && count($links) === 1"}
index aca890d6c3a549fca924fa02a58a5fa384a7dae6..8c10b2cba7df49f27d53e0cc1d1df353365ee64e 100644 (file)
@@ -5,7 +5,7 @@
 <div id="install">
     <h1>Shaarli</h1>
     It looks like it's the first time you run Shaarli. Please configure it:<br>
-    <form method="POST" action="#" name="installform" id="installform">
+    <form method="POST" action="{$base_path}/install" name="installform" id="installform">
         <table>
             <tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr>
             <tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr>
index 8db8f70b902778b4ba67eb9a1c689559a2bedcf4..00896eb5ec65153cab29823bd738ece6b0ff2cb6 100644 (file)
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <link type="text/css" rel="stylesheet" href="inc/awesomplete.css#" />
     {include="includes"}
 </head>
 <body>
@@ -84,7 +83,7 @@
                 <div class="thumbnail">
                     <a href="{$value.real_url}">
                         {ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore}
-                        <img data-src="{$value.thumbnail}#" class="b-lazy"
+                        <img data-src="{$base_path}/{$value.thumbnail}#" class="b-lazy"
                              src=""
                              alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
                     </a>
             <div class="linkcontainer">
                 {if="$is_logged_in"}
                     <div class="linkeditbuttons">
-                        <form method="GET" class="buttoneditform">
-                            <input type="hidden" name="edit_link" value="{$value.id}">
-                            <input type="image" alt="Edit" src="{$asset_path}/img/edit_icon.png#" title="Edit" class="button_edit">
-                        </form><br>
-                        <form method="GET" class="buttoneditform">
-                            <input type="hidden" name="lf_linkdate" value="{$value.id}">
-                            <input type="hidden" name="token" value="{$token}">
-                            <input type="hidden" name="delete_link">
-                            <input type="image" alt="Delete" src="{$asset_path}/img/delete_icon.png#" title="Delete"
-                                   class="button_delete" onClick="return confirmDeleteLink();">
-                        </form>
+                        <a href="{$base_path}/admin/shaare/{$value.id}" title="Edit" class="button_edit">
+                            <img src="{$asset_path}/img/edit_icon.png#">
+                        </a>
+                        <br>
+                        <a href="{$base_path}/admin/shaare/delete?id={$value.id}&amp;token={$token}" label="Delete"
+                           onClick="return confirmDeleteLink();"
+                           class="button_delete"
+                        >
+                            <img src="{$asset_path}/img/delete_icon.png#">
+                        </a>
                     </div>
                 {/if}
                 <span class="linktitle">
                 {if="!$hide_timestamps || $is_logged_in"}
                     {$updated=$value.updated_timestamp ? 'Edited: '. format_date($value.updated) : 'Permalink'}
                     <span class="linkdate" title="Permalink">
-                        <a href="{$base_path}/?{$value.shorturl}">
+                        <a href="{$base_path}/shaare/{$value.shorturl}">
                             <span title="{$updated}">
                                 {$value.created|format_date}
                                 {if="$value.updated_timestamp"}*{/if}
                         </a> -
                     </span>
                 {else}
-                    <span class="linkdate" title="Short link here"><a href="{$base_path}/?{$value.shorturl}">permalink</a> - </span>
+                    <span class="linkdate" title="Short link here"><a href="{$base_path}/shaare/{$value.shorturl}">permalink</a> - </span>
                 {/if}
 
                 {loop="$value.link_plugin"}
index a37920667883f5182a083be7b8387bcbf09a7791..6aa20ab193453df7baaa9128c0106bfb0c3f50dd 100644 (file)
@@ -11,7 +11,7 @@
   {include="page.header"}
 
   <div id="headerform">
-    <form method="post" name="loginform">
+    <form method="post" name="loginform" action="{$base_path}/login">
       <label for="login">Login: <input type="text" id="login" name="login" tabindex="1"
          {if="!empty($username)"}value="{$username}"{/if}>
       </label>
index 6d9021e3678c25cfa09d6b5a897db07ba929b448..0fe4c7368f10ac071b76565fd2a2cdcc1ddb822c 100644 (file)
@@ -30,5 +30,7 @@
 {/if}
 
 {loop="$plugins_footer.js_files"}
-       <script src="{$value}#"></script>
+       <script src="{$base_path}/{$value}#"></script>
 {/loop}
+
+<input type="hidden" name="js_base_path" value="{$base_path}" />
index a04c77c2905d1372ee7aa9a7b120a3da6532ef78..d0972cd15befc4b4d0900e75e532c884b4563ccf 100644 (file)
@@ -86,6 +86,7 @@
         <input type="submit" value="Save"/>
       </div>
     </section>
+    <input type="hidden" name="token" value="{$token}">
   </form>
 
   <form action="{$base_path}/admin/plugins" method="POST">
         </div>
       </div>
     </section>
+    <input type="hidden" name="token" value="{$token}">
   </form>
 
 </div>
index a1537f9c0b5864f62b5606951547caad07dbaf00..18f296f7ad73fff10d1f5c77c216962dc8ea3dca 100644 (file)
@@ -23,7 +23,6 @@
 <input type="hidden" name="ids" value="{function="implode(',', $ids)"}" />
 
 {include="page.footer"}
-<input type="hidden" name="js_base_path" value="{$base_path}" />
 <script src="{$asset_path}/js/thumbnails_update.min.js?v={$version_hash}#"></script>
 </body>
 </html>