]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - index.php
Process main page (linklist) through Slim controller
[github/shaarli/Shaarli.git] / index.php
index a07de74d01508e6003d43b4cfd3de97fca8947f9..2737c22cdfea7a2f8a4bc802daae77c4a2e0f171 100644 (file)
--- a/index.php
+++ b/index.php
@@ -61,30 +61,15 @@ require_once 'application/TimeZone.php';
 require_once 'application/Utils.php';
 
 use Shaarli\ApplicationUtils;
-use Shaarli\Bookmark\Bookmark;
 use Shaarli\Bookmark\BookmarkFileService;
-use Shaarli\Bookmark\BookmarkFilter;
-use Shaarli\Bookmark\BookmarkServiceInterface;
-use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
 use Shaarli\Config\ConfigManager;
 use Shaarli\Container\ContainerBuilder;
-use Shaarli\Feed\CachedPage;
-use Shaarli\Feed\FeedBuilder;
-use Shaarli\Formatter\BookmarkMarkdownFormatter;
-use Shaarli\Formatter\FormatterFactory;
 use Shaarli\History;
 use Shaarli\Languages;
-use Shaarli\Netscape\NetscapeBookmarkUtils;
 use Shaarli\Plugin\PluginManager;
 use Shaarli\Render\PageBuilder;
-use Shaarli\Render\PageCacheManager;
-use Shaarli\Render\ThemeUtils;
-use Shaarli\Router;
 use Shaarli\Security\LoginManager;
 use Shaarli\Security\SessionManager;
-use Shaarli\Thumbnailer;
-use Shaarli\Updater\Updater;
-use Shaarli\Updater\UpdaterUtils;
 use Slim\App;
 
 // Ensure the PHP version is supported
@@ -196,20 +181,6 @@ if (! is_file($conf->getConfigFileExt())) {
 
 $loginManager->checkLoginState($_COOKIE, $clientIpId);
 
-/**
- * Adapter function to ensure compatibility with third-party templates
- *
- * @see https://github.com/shaarli/Shaarli/pull/1086
- *
- * @return bool true when the user is logged in, false otherwise
- */
-function isLoggedIn()
-{
-    global $loginManager;
-    return $loginManager->isLoggedIn();
-}
-
-
 // ------------------------------------------------------------------------------------------
 // Process login form: Check if login/password is correct.
 if (isset($_POST['login'])) {
@@ -300,473 +271,6 @@ if (!isset($_SESSION['tokens'])) {
     $_SESSION['tokens']=array();  // Token are attached to the session.
 }
 
-/**
- * Renders the linklist
- *
- * @param pageBuilder              $PAGE          pageBuilder instance.
- * @param BookmarkServiceInterface $linkDb        instance.
- * @param ConfigManager            $conf          Configuration Manager instance.
- * @param PluginManager            $pluginManager Plugin Manager instance.
- */
-function showLinkList($PAGE, $linkDb, $conf, $pluginManager, $loginManager)
-{
-    buildLinkList($PAGE, $linkDb, $conf, $pluginManager, $loginManager);
-    $PAGE->renderPage('linklist');
-}
-
-/**
- * Render HTML page (according to URL parameters and user rights)
- *
- * @param ConfigManager            $conf           Configuration Manager instance.
- * @param PluginManager            $pluginManager  Plugin Manager instance,
- * @param BookmarkServiceInterface $bookmarkService
- * @param History                  $history        instance
- * @param SessionManager           $sessionManager SessionManager instance
- * @param LoginManager             $loginManager   LoginManager instance
- */
-function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionManager, $loginManager)
-{
-    $pageCacheManager = new PageCacheManager($conf->get('resource.page_cache'), $loginManager->isLoggedIn());
-    $updater = new Updater(
-        UpdaterUtils::read_updates_file($conf->get('resource.updates')),
-        $bookmarkService,
-        $conf,
-        $loginManager->isLoggedIn()
-    );
-    try {
-        $newUpdates = $updater->update();
-        if (! empty($newUpdates)) {
-            UpdaterUtils::write_updates_file(
-                $conf->get('resource.updates'),
-                $updater->getDoneUpdates()
-            );
-
-            $pageCacheManager->invalidateCaches();
-        }
-    } catch (Exception $e) {
-        die($e->getMessage());
-    }
-
-    $PAGE = new PageBuilder($conf, $_SESSION, $bookmarkService, $sessionManager->generateToken(), $loginManager->isLoggedIn());
-    $PAGE->assign('linkcount', $bookmarkService->count(BookmarkFilter::$ALL));
-    $PAGE->assign('privateLinkcount', $bookmarkService->count(BookmarkFilter::$PRIVATE));
-    $PAGE->assign('plugin_errors', $pluginManager->getErrors());
-
-    // Determine which page will be rendered.
-    $query = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : '';
-    $targetPage = Router::findPage($query, $_GET, $loginManager->isLoggedIn());
-
-    if (// if the user isn't logged in
-        !$loginManager->isLoggedIn() &&
-        // and Shaarli doesn't have public content...
-        $conf->get('privacy.hide_public_links') &&
-        // and is configured to enforce the login
-        $conf->get('privacy.force_login') &&
-        // and the current page isn't already the login page
-        $targetPage !== Router::$PAGE_LOGIN &&
-        // and the user is not requesting a feed (which would lead to a different content-type as expected)
-        $targetPage !== Router::$PAGE_FEED_ATOM &&
-        $targetPage !== Router::$PAGE_FEED_RSS
-    ) {
-        // force current page to be the login page
-        $targetPage = Router::$PAGE_LOGIN;
-    }
-
-    // Call plugin hooks for header, footer and includes, specifying which page will be rendered.
-    // Then assign generated data to RainTPL.
-    $common_hooks = array(
-        'includes',
-        'header',
-        'footer',
-    );
-
-    foreach ($common_hooks as $name) {
-        $plugin_data = array();
-        $pluginManager->executeHooks(
-            'render_' . $name,
-            $plugin_data,
-            array(
-                'target' => $targetPage,
-                'loggedin' => $loginManager->isLoggedIn()
-            )
-        );
-        $PAGE->assign('plugins_' . $name, $plugin_data);
-    }
-
-    // -------- Display login form.
-    if ($targetPage == Router::$PAGE_LOGIN) {
-        header('Location: ./login');
-        exit;
-    }
-    // -------- User wants to logout.
-    if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=logout')) {
-        header('Location: ./logout');
-        exit;
-    }
-
-    // -------- Picture wall
-    if ($targetPage == Router::$PAGE_PICWALL) {
-        header('Location: ./picture-wall');
-        exit;
-    }
-
-    // -------- Tag cloud
-    if ($targetPage == Router::$PAGE_TAGCLOUD) {
-        header('Location: ./tags/cloud');
-        exit;
-    }
-
-    // -------- Tag list
-    if ($targetPage == Router::$PAGE_TAGLIST) {
-        header('Location: ./tags/list');
-        exit;
-    }
-
-    // Daily page.
-    if ($targetPage == Router::$PAGE_DAILY) {
-        $dayParam = !empty($_GET['day']) ? '?day=' . escape($_GET['day']) : '';
-        header('Location: ./daily'. $dayParam);
-        exit;
-    }
-
-    // ATOM and RSS feed.
-    if ($targetPage == Router::$PAGE_FEED_ATOM || $targetPage == Router::$PAGE_FEED_RSS) {
-        $feedType = $targetPage == Router::$PAGE_FEED_RSS ? FeedBuilder::$FEED_RSS : FeedBuilder::$FEED_ATOM;
-
-        header('Location: ./feed/'. $feedType .'?'. http_build_query($_GET));
-        exit;
-    }
-
-    // Display opensearch plugin (XML)
-    if ($targetPage == Router::$PAGE_OPENSEARCH) {
-        header('Location: ./open-search');
-        exit;
-    }
-
-    // -------- User clicks on a tag in a link: The tag is added to the list of searched tags (searchtags=...)
-    if (isset($_GET['addtag'])) {
-        header('Location: ./add-tag/'. $_GET['addtag']);
-        exit;
-    }
-
-    // -------- User clicks on a tag in result count: Remove the tag from the list of searched tags (searchtags=...)
-    if (isset($_GET['removetag'])) {
-        header('Location: ./remove-tag/'. $_GET['removetag']);
-        exit;
-    }
-
-    // -------- User wants to change the number of bookmarks per page (linksperpage=...)
-    if (isset($_GET['linksperpage'])) {
-        header('Location: ./links-per-page?nb='. $_GET['linksperpage']);
-        exit;
-    }
-
-    // -------- User wants to see only private bookmarks (toggle)
-    if (isset($_GET['visibility'])) {
-        header('Location: ./visibility/'. $_GET['visibility']);
-        exit;
-    }
-
-    // -------- User wants to see only untagged bookmarks (toggle)
-    if (isset($_GET['untaggedonly'])) {
-        header('Location: ./untagged-only');
-        exit;
-    }
-
-    // -------- Handle other actions allowed for non-logged in users:
-    if (!$loginManager->isLoggedIn()) {
-        // User tries to post new link but is not logged in:
-        // Show login screen, then redirect to ?post=...
-        if (isset($_GET['post'])) {
-            header( // Redirect to login page, then back to post link.
-                'Location: ./login?post='.urlencode($_GET['post']).
-                (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):'').
-                (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):'').
-                (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):'').
-                (!empty($_GET['source'])?'&source='.urlencode($_GET['source']):'')
-            );
-            exit;
-        }
-
-        showLinkList($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager);
-        if (isset($_GET['edit_link'])) {
-            header('Location: ./login?edit_link='. escape($_GET['edit_link']));
-            exit;
-        }
-
-        exit; // Never remove this one! All operations below are reserved for logged in user.
-    }
-
-    // -------- All other functions are reserved for the registered user:
-
-    // TODO: Remove legacy admin route redirections. We'll only keep public URL.
-
-    // -------- Display the Tools menu if requested (import/export/bookmarklet...)
-    if ($targetPage == Router::$PAGE_TOOLS) {
-        header('Location: ./admin/tools');
-        exit;
-    }
-
-    // -------- User wants to change his/her password.
-    if ($targetPage == Router::$PAGE_CHANGEPASSWORD) {
-        header('Location: ./admin/password');
-        exit;
-    }
-
-    // -------- User wants to change configuration
-    if ($targetPage == Router::$PAGE_CONFIGURE) {
-        header('Location: ./admin/configure');
-        exit;
-    }
-
-    // -------- User wants to rename a tag or delete it
-    if ($targetPage == Router::$PAGE_CHANGETAG) {
-        header('Location: ./admin/tags');
-        exit;
-    }
-
-    // -------- User wants to add a link without using the bookmarklet: Show form.
-    if ($targetPage == Router::$PAGE_ADDLINK) {
-        header('Location: ./admin/shaare');
-        exit;
-    }
-
-    // -------- User clicked the "Save" button when editing a link: Save link to database.
-    if (isset($_POST['save_edit'])) {
-        // This route is no longer supported in legacy mode
-        header('Location: ./');
-        exit;
-    }
-
-    // -------- User clicked the "Delete" button when editing a link: Delete link from database.
-    if ($targetPage == Router::$PAGE_DELETELINK) {
-        $ids = $_GET['lf_linkdate'] ?? '';
-        $token = $_GET['token'] ?? '';
-
-        header('Location: ./admin/shaare/delete?id=' . $ids . '&token=' . $token);
-        exit;
-    }
-
-    // -------- User clicked either "Set public" or "Set private" bulk operation
-    if ($targetPage == Router::$PAGE_CHANGE_VISIBILITY) {
-        header('Location: ./admin/shaare/visibility?id=' . $_GET['token']);
-        exit;
-    }
-
-    // -------- User clicked the "EDIT" button on a link: Display link edit form.
-    if (isset($_GET['edit_link'])) {
-        $id = (int) escape($_GET['edit_link']);
-        header('Location: ./admin/shaare/' . $id);
-        exit;
-    }
-
-    // -------- User want to post a new link: Display link edit form.
-    if (isset($_GET['post'])) {
-        header('Location: ./admin/shaare?' . http_build_query($_GET));
-        exit;
-    }
-
-    if ($targetPage == Router::$PAGE_PINLINK) {
-        // This route is no longer supported in legacy mode
-        header('Location: ./');
-        exit;
-    }
-
-    if ($targetPage == Router::$PAGE_EXPORT) {
-        header('Location: ./admin/export');
-        exit;
-    }
-
-    if ($targetPage == Router::$PAGE_IMPORT) {
-        header('Location: ./admin/import');
-        exit;
-    }
-
-    // Plugin administration page
-    if ($targetPage == Router::$PAGE_PLUGINSADMIN) {
-        header('Location: ./admin/plugins');
-        exit;
-    }
-
-    // Plugin administration form action
-    if ($targetPage == Router::$PAGE_SAVE_PLUGINSADMIN) {
-        // This route is no longer supported in legacy mode
-        header('Location: ./admin/plugins');
-        exit;
-    }
-
-    // Get a fresh token
-    if ($targetPage == Router::$GET_TOKEN) {
-        header('Location: ./admin/token');
-        exit;
-    }
-
-    // -------- Thumbnails Update
-    if ($targetPage == Router::$PAGE_THUMBS_UPDATE) {
-        header('Location: ./admin/thumbnails');
-        exit;
-    }
-
-    // -------- Single Thumbnail Update
-    if ($targetPage == Router::$AJAX_THUMB_UPDATE) {
-        // This route is no longer supported in legacy mode
-        http_response_code(404);
-        exit;
-    }
-
-    // -------- Otherwise, simply display search form and bookmarks:
-    showLinkList($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager);
-    exit;
-}
-
-/**
- * Template for the list of bookmarks (<div id="linklist">)
- * This function fills all the necessary fields in the $PAGE for the template 'linklist.html'
- *
- * @param pageBuilder              $PAGE          pageBuilder instance.
- * @param BookmarkServiceInterface $linkDb        LinkDB instance.
- * @param ConfigManager            $conf          Configuration Manager instance.
- * @param PluginManager            $pluginManager Plugin Manager instance.
- * @param LoginManager             $loginManager  LoginManager instance
- */
-function buildLinkList($PAGE, $linkDb, $conf, $pluginManager, $loginManager)
-{
-    $factory = new FormatterFactory($conf, $loginManager->isLoggedIn());
-    $formatter = $factory->getFormatter();
-
-    // Used in templates
-    if (isset($_GET['searchtags'])) {
-        if (! empty($_GET['searchtags'])) {
-            $searchtags = escape(normalize_spaces($_GET['searchtags']));
-        } else {
-            $searchtags = false;
-        }
-    } else {
-        $searchtags = '';
-    }
-    $searchterm = !empty($_GET['searchterm']) ? escape(normalize_spaces($_GET['searchterm'])) : '';
-
-    // Smallhash filter
-    if (! empty($_SERVER['QUERY_STRING'])
-        && preg_match('/^[a-zA-Z0-9-_@]{6}($|&|#)/', $_SERVER['QUERY_STRING'])) {
-        try {
-            $linksToDisplay = $linkDb->findByHash($_SERVER['QUERY_STRING']);
-        } catch (BookmarkNotFoundException $e) {
-            $PAGE->render404($e->getMessage());
-            exit;
-        }
-    } else {
-        // Filter bookmarks according search parameters.
-        $visibility = ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : null;
-        $request = [
-            'searchtags' => $searchtags,
-            'searchterm' => $searchterm,
-        ];
-        $linksToDisplay = $linkDb->search($request, $visibility, false, !empty($_SESSION['untaggedonly']));
-    }
-
-    // ---- Handle paging.
-    $keys = array();
-    foreach ($linksToDisplay as $key => $value) {
-        $keys[] = $key;
-    }
-
-    // Select articles according to paging.
-    $pagecount = ceil(count($keys) / $_SESSION['LINKS_PER_PAGE']);
-    $pagecount = $pagecount == 0 ? 1 : $pagecount;
-    $page= empty($_GET['page']) ? 1 : intval($_GET['page']);
-    $page = $page < 1 ? 1 : $page;
-    $page = $page > $pagecount ? $pagecount : $page;
-    // Start index.
-    $i = ($page-1) * $_SESSION['LINKS_PER_PAGE'];
-    $end = $i + $_SESSION['LINKS_PER_PAGE'];
-
-    $thumbnailsEnabled = $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE;
-    if ($thumbnailsEnabled) {
-        $thumbnailer = new Thumbnailer($conf);
-    }
-
-    $linkDisp = array();
-    while ($i<$end && $i<count($keys)) {
-        $link = $formatter->format($linksToDisplay[$keys[$i]]);
-
-        // Logged in, thumbnails enabled, not a note,
-        // and (never retrieved yet or no valid cache file)
-        if ($loginManager->isLoggedIn()
-            && $thumbnailsEnabled
-            && !$linksToDisplay[$keys[$i]]->isNote()
-            && $linksToDisplay[$keys[$i]]->getThumbnail() !== false
-            && ! is_file($linksToDisplay[$keys[$i]]->getThumbnail())
-        ) {
-            $linksToDisplay[$keys[$i]]->setThumbnail($thumbnailer->get($link['url']));
-            $linkDb->set($linksToDisplay[$keys[$i]], false);
-            $updateDB = true;
-            $link['thumbnail'] = $linksToDisplay[$keys[$i]]->getThumbnail();
-        }
-
-        // Check for both signs of a note: starting with ? and 7 chars long.
-//        if ($link['url'][0] === '?' && strlen($link['url']) === 7) {
-//            $link['url'] = index_url($_SERVER) . $link['url'];
-//        }
-
-        $linkDisp[$keys[$i]] = $link;
-        $i++;
-    }
-
-    // If we retrieved new thumbnails, we update the database.
-    if (!empty($updateDB)) {
-        $linkDb->save();
-    }
-
-    // Compute paging navigation
-    $searchtagsUrl = $searchtags === '' ? '' : '&searchtags=' . urlencode($searchtags);
-    $searchtermUrl = empty($searchterm) ? '' : '&searchterm=' . urlencode($searchterm);
-    $previous_page_url = '';
-    if ($i != count($keys)) {
-        $previous_page_url = '?page=' . ($page+1) . $searchtermUrl . $searchtagsUrl;
-    }
-    $next_page_url='';
-    if ($page>1) {
-        $next_page_url = '?page=' . ($page-1) . $searchtermUrl . $searchtagsUrl;
-    }
-
-    // Fill all template fields.
-    $data = array(
-        'previous_page_url' => $previous_page_url,
-        'next_page_url' => $next_page_url,
-        'page_current' => $page,
-        'page_max' => $pagecount,
-        'result_count' => count($linksToDisplay),
-        'search_term' => $searchterm,
-        'search_tags' => $searchtags,
-        'visibility' => ! empty($_SESSION['visibility']) ? $_SESSION['visibility'] : '',
-        'links' => $linkDisp,
-    );
-
-    // If there is only a single link, we change on-the-fly the title of the page.
-    if (count($linksToDisplay) == 1) {
-        $data['pagetitle'] = $linksToDisplay[$keys[0]]->getTitle() .' - '. $conf->get('general.title');
-    } elseif (! empty($searchterm) || ! empty($searchtags)) {
-        $data['pagetitle'] = t('Search: ');
-        $data['pagetitle'] .= ! empty($searchterm) ? $searchterm .' ' : '';
-        $bracketWrap = function ($tag) {
-            return '['. $tag .']';
-        };
-        $data['pagetitle'] .= ! empty($searchtags)
-            ? implode(' ', array_map($bracketWrap, preg_split('/\s+/', $searchtags))).' '
-            : '';
-        $data['pagetitle'] .= '- '. $conf->get('general.title');
-    }
-
-    $pluginManager->executeHooks('render_linklist', $data, array('loggedin' => $loginManager->isLoggedIn()));
-
-    foreach ($data as $key => $value) {
-        $PAGE->assign($key, $value);
-    }
-
-    return;
-}
-
 /**
  * Installation
  * This function should NEVER be called if the file data/config.php exists.
@@ -882,19 +386,6 @@ if (!isset($_SESSION['LINKS_PER_PAGE'])) {
     $_SESSION['LINKS_PER_PAGE'] = $conf->get('general.links_per_page', 20);
 }
 
-try {
-    $history = new History($conf->get('resource.history'));
-} catch (Exception $e) {
-    die($e->getMessage());
-}
-
-$linkDb = new BookmarkFileService($conf, $history, $loginManager->isLoggedIn());
-
-if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=dailyrss')) {
-    header('Location: ./daily-rss');
-    exit;
-}
-
 $containerBuilder = new ContainerBuilder($conf, $sessionManager, $loginManager);
 $container = $containerBuilder->build();
 $app = new App($container);
@@ -918,13 +409,15 @@ $app->group('/api/v1', function () {
 
 $app->group('', function () {
     /* -- PUBLIC --*/
-    $this->get('/login', '\Shaarli\Front\Controller\Visitor\LoginController:index');
+    $this->get('/', '\Shaarli\Front\Controller\Visitor\BookmarkListController:index');
+    $this->get('/shaare/{hash}', '\Shaarli\Front\Controller\Visitor\BookmarkListController:permalink');
+    $this->get('/login', '\Shaarli\Front\Controller\Visitor\LoginController:index')->setName('login');
     $this->get('/picture-wall', '\Shaarli\Front\Controller\Visitor\PictureWallController:index');
     $this->get('/tags/cloud', '\Shaarli\Front\Controller\Visitor\TagCloudController:cloud');
     $this->get('/tags/list', '\Shaarli\Front\Controller\Visitor\TagCloudController:list');
     $this->get('/daily', '\Shaarli\Front\Controller\Visitor\DailyController:index');
-    $this->get('/daily-rss', '\Shaarli\Front\Controller\Visitor\DailyController:rss');
-    $this->get('/feed/atom', '\Shaarli\Front\Controller\Visitor\FeedController:atom');
+    $this->get('/daily-rss', '\Shaarli\Front\Controller\Visitor\DailyController:rss')->setName('rss');
+    $this->get('/feed/atom', '\Shaarli\Front\Controller\Visitor\FeedController:atom')->setName('atom');
     $this->get('/feed/rss', '\Shaarli\Front\Controller\Visitor\FeedController:rss');
     $this->get('/open-search', '\Shaarli\Front\Controller\Visitor\OpenSearchController:index');
 
@@ -967,19 +460,4 @@ $app->group('', function () {
 
 $response = $app->run(true);
 
-// Hack to make Slim and Shaarli router work together:
-// If a Slim route isn't found and NOT API call, we call renderPage().
-if ($response->getStatusCode() == 404 && strpos($_SERVER['REQUEST_URI'], '/api/v1') === false) {
-    // We use UTF-8 for proper international characters handling.
-    header('Content-Type: text/html; charset=utf-8');
-    renderPage($conf, $pluginManager, $linkDb, $history, $sessionManager, $loginManager);
-} else {
-    $response = $response
-        ->withHeader('Access-Control-Allow-Origin', '*')
-        ->withHeader(
-            'Access-Control-Allow-Headers',
-            'X-Requested-With, Content-Type, Accept, Origin, Authorization'
-        )
-        ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
-    $app->respond($response);
-}
+$app->respond($response);