[FEATURE] Storable Filters for Upgrade Analysis 50/51050/21
authorAnja Leichsenring <aleichsenring@ab-softlab.de>
Tue, 27 Dec 2016 16:22:09 +0000 (17:22 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sun, 5 Feb 2017 21:53:21 +0000 (22:53 +0100)
User can mark each file as 'hide from my view'. This
selection is stored in registry and applies for every user alike.

All hidden files are accessible via a section and can be restored.
This selection again applies for all users.

Change-Id: Ia3108977ca5cb180dd0e1925ff918ffb03452249
Resolves: #79420
Releases: master
Reviewed-on: https://review.typo3.org/51050
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Tested-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
16 files changed:
typo3/sysext/core/Documentation/Changelog/master/Feature-79420-HideFilesFromListOfDocumentation.rst [new file with mode: 0644]
typo3/sysext/core/ext_tables.sql
typo3/sysext/install/Classes/Controller/Action/Ajax/FilterManager.php [new file with mode: 0644]
typo3/sysext/install/Classes/Controller/Action/Ajax/RemoveIgnoredItems.php [new file with mode: 0644]
typo3/sysext/install/Classes/Controller/Action/Ajax/SaveIgnoredItems.php [new file with mode: 0644]
typo3/sysext/install/Classes/Controller/Action/Tool/UpgradeAnalysis.php
typo3/sysext/install/Classes/Controller/AjaxController.php
typo3/sysext/install/Classes/UpgradeAnalysis/DocumentationFile.php
typo3/sysext/install/Resources/Private/Partials/Action/Ajax/UpgradeAnalysis/ListDocumentation.html [deleted file]
typo3/sysext/install/Resources/Private/Partials/Action/Tool/UpgradeAnalysis/ListDocumentation.html [new file with mode: 0644]
typo3/sysext/install/Resources/Private/Partials/Action/Tool/UpgradeAnalysis/PanelItem.html [new file with mode: 0644]
typo3/sysext/install/Resources/Private/Templates/Action/Ajax/FilterManager.html [new file with mode: 0644]
typo3/sysext/install/Resources/Private/Templates/Action/Ajax/RemoveIgnoredItems.html [new file with mode: 0644]
typo3/sysext/install/Resources/Private/Templates/Action/Tool/UpgradeAnalysis.html
typo3/sysext/install/Resources/Public/JavaScript/Install.js
typo3/sysext/install/Tests/Unit/UpgradeAnalysis/DocumentationFileTest.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-79420-HideFilesFromListOfDocumentation.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-79420-HideFilesFromListOfDocumentation.rst
new file mode 100644 (file)
index 0000000..674a6fe
--- /dev/null
@@ -0,0 +1,22 @@
+.. include:: ../../Includes.txt
+
+=======================================================
+Feature: #79420 - Hide files from list of documentation
+=======================================================
+
+See :issue:`79420`
+
+Description
+===========
+
+The list of displayed documentation files gets pretty long over time. The user might want to hide those already tackled or of no interest from listing. This is possible via checkboxes.
+
+A new section has been introduced that lists those hidden files to bring them back if necessary.
+
+
+Impact
+======
+
+The list of documentation files can be shortened now.
+
+.. index:: PHP-API
\ No newline at end of file
index 80becf1..666c751 100644 (file)
@@ -174,7 +174,7 @@ CREATE TABLE sys_registry (
        uid int(11) unsigned NOT NULL auto_increment,
        entry_namespace varchar(128) DEFAULT '' NOT NULL,
        entry_key varchar(128) DEFAULT '' NOT NULL,
-       entry_value blob,
+       entry_value mediumblob,
        PRIMARY KEY (uid),
        UNIQUE KEY entry_identifier (entry_namespace,entry_key)
 );
diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/FilterManager.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/FilterManager.php
new file mode 100644 (file)
index 0000000..c78d886
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+declare(strict_types=1);
+namespace TYPO3\CMS\Install\Controller\Action\Ajax;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+use TYPO3\CMS\Core\Registry;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Install\UpgradeAnalysis\DocumentationFile;
+
+/**
+  * Reveal documentation files hidden from views
+  */
+class FilterManager extends AbstractAjaxAction
+{
+
+    /**
+     * Executes the action
+     *
+     * @return string Rendered content
+     */
+    protected function executeAction(): string
+    {
+        $registry = new Registry();
+        $ignoredFiles = $registry->get('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles', []);
+        $documentationFileService = GeneralUtility::makeInstance(DocumentationFile::class);
+        $files = [];
+        foreach ($ignoredFiles as $filePath) {
+            $file = current($documentationFileService->getListEntry($filePath));
+            $files[] = $file['headline'];
+        }
+        $this->view->assign('files', $files);
+        return $this->view->render();
+    }
+}
diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/RemoveIgnoredItems.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/RemoveIgnoredItems.php
new file mode 100644 (file)
index 0000000..e25fd9f
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+declare(strict_types=1);
+
+namespace TYPO3\CMS\Install\Controller\Action\Ajax;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+use TYPO3\CMS\Core\Registry;
+use TYPO3\CMS\Install\UpgradeAnalysis\DocumentationFile;
+
+/**
+ * Remove ignored items from registry and therefor bring them back
+ */
+class RemoveIgnoredItems extends AbstractAjaxAction
+{
+
+    /**
+     * Executes the action
+     *
+     * @return string Rendered content
+     */
+    protected function executeAction(): string
+    {
+        $registry = new Registry();
+        $file = $this->postValues['ignoreFile'];
+
+        $ignoredFiles = $registry->get('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles', []);
+        $key = array_search($file, $ignoredFiles);
+        unset($ignoredFiles[$key]);
+
+        $registry->set('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles', $ignoredFiles);
+
+        $documentationFileService = new DocumentationFile();
+        $fileInformation = $documentationFileService->getListEntry($file);
+        $issueNumber = key($fileInformation);
+        $this->view->assign('fileArray', current($fileInformation));
+        $this->view->assign('issueNumber', $issueNumber);
+
+        return $this->view->render();
+    }
+}
diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/SaveIgnoredItems.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/SaveIgnoredItems.php
new file mode 100644 (file)
index 0000000..e2eef65
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+declare(strict_types=1);
+
+namespace TYPO3\CMS\Install\Controller\Action\Ajax;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+use TYPO3\CMS\Core\Registry;
+
+/**
+ * Save ignored documentation file items and hide them from display
+ */
+class SaveIgnoredItems extends AbstractAjaxAction
+{
+
+    /**
+     * Executes the action
+     *
+     * @return string content
+     */
+    protected function executeAction(): string
+    {
+        $registry = new Registry();
+        $file = $this->postValues['ignoreFile'];
+
+        $ignoredFiles = $registry->get('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles');
+        if ($file !== null && strlen($file) > 0) {
+            $ignoredFiles[] = $file;
+
+            $registry->set('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles', $ignoredFiles);
+        }
+        return json_encode('');
+    }
+}
index a409027..96bb218 100644 (file)
@@ -41,6 +41,17 @@ class UpgradeAnalysis extends AbstractAction
             PATH_site . ExtensionManagementUtility::siteRelPath('core') . 'Documentation/Changelog'
         );
 
+        /** @var $formProtection \TYPO3\CMS\Core\FormProtection\InstallToolFormProtection */
+        $formProtection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get(
+            \TYPO3\CMS\Core\FormProtection\InstallToolFormProtection::class
+        );
+        $saveIgnoredItemsToken = $formProtection->generateToken('installTool', 'saveIgnoredItems');
+        $removeIgnoredItemsToken = $formProtection->generateToken('installTool', 'removeIgnoredItems');
+        $this->view->assignMultiple([
+            'saveIgnoredItemsToken' => $saveIgnoredItemsToken,
+            'removeIgnoredItemsToken' => $removeIgnoredItemsToken,
+        ]);
+
         $this->view->assign('files', $documentationFiles);
         return $this->view->render();
     }
index 876d344..23d9090 100644 (file)
@@ -46,6 +46,9 @@ class AjaxController extends AbstractController
         'environmentStatus',
         'tcaExtTablesCheck',
         'tcaMigrationsCheck',
+        'filterManager',
+        'saveIgnoredItems',
+        'removeIgnoredItems',
     ];
 
     /**
index 75cb22a..cbc2622 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 declare(strict_types=1);
+
 namespace TYPO3\CMS\Install\UpgradeAnalysis;
 
 /*
@@ -15,6 +16,8 @@ namespace TYPO3\CMS\Install\UpgradeAnalysis;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Registry;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -22,6 +25,10 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class DocumentationFile
 {
+    /**
+     * @var Registry
+     */
+    protected $registry;
 
     /**
      * @var array Unified array of used tags
@@ -29,13 +36,39 @@ class DocumentationFile
     protected $tagsTotal = [];
 
     /**
+     * all files handled in this Class need to reside inside the changelog dir
+     * this is a security measure to protect system files
+     *
+     * @var string
+     */
+    protected $changelogPath = '';
+
+    /**
+     * DocumentationFile constructor.
+     * @param Registry|null $registry
+     */
+    public function __construct(Registry $registry = null, $changelogDir = '')
+    {
+        $this->registry = $registry;
+        if ($this->registry === null) {
+            $this->registry = new Registry();
+        }
+        $this->changelogPath = $changelogDir !== '' ? $changelogDir : realpath(PATH_site . ExtensionManagementUtility::siteRelPath('core') . 'Documentation/Changelog');
+    }
+
+    /**
      * Traverse given directory, select files
      *
      * @param string $path
      * @return array file details of affected documentation files
+     * @throws \InvalidArgumentException
      */
     public function findDocumentationFiles(string $path): array
     {
+        if (strcasecmp($path, $this->changelogPath) < 0 || strpos($path, $this->changelogPath) === false) {
+            throw new \InvalidArgumentException('the given path does not belong to the changelog dir. Aborting', 1485425530);
+        }
+
         $documentationFiles = [];
         $versionDirectories = scandir($path);
 
@@ -51,6 +84,29 @@ class DocumentationFile
     }
 
     /**
+     * Get main information from a .rst file
+     *
+     * @param string $file
+     * @return array
+     */
+    public function getListEntry(string $file): array
+    {
+        if (strcasecmp($file, $this->changelogPath) < 0 || strpos($file, $this->changelogPath) === false) {
+            throw new \InvalidArgumentException('the given file does not belong to the changelog dir. Aborting', 1485425531);
+        }
+        $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+        $headline = $this->extractHeadline($lines);
+        $entry['headline'] = $headline;
+        $entry['filepath'] = $file;
+        $entry['tags'] = $this->extractTags($lines);
+        $entry['tagList'] = implode(',', $entry['tags']);
+        $entry['content'] = file_get_contents($file);
+        $issueNumber = $this->extractIssueNumber($headline);
+
+        return [$issueNumber => $entry];
+    }
+
+    /**
      * True if file should be considered
      *
      * @param array $fileInfo
@@ -58,7 +114,13 @@ class DocumentationFile
      */
     protected function isRelevantFile(array $fileInfo): bool
     {
-        return $fileInfo['extension'] === 'rst' && $fileInfo['filename'] !== 'Index';
+        $isRelevantFile = $fileInfo['extension'] === 'rst' && $fileInfo['filename'] !== 'Index';
+        // file might be ignored by users choice
+        if ($isRelevantFile && $this->isFileIgnoredByUsersChoice($fileInfo['basename'])) {
+            $isRelevantFile = false;
+        }
+
+        return $isRelevantFile;
     }
 
     /**
@@ -114,8 +176,7 @@ class DocumentationFile
     }
 
     /**
-     * First line is headline mark, skip it
-     * second line is headline
+     * Skip include line and markers, use the first line actually containing text
      *
      * @param array $lines
      * @return string
@@ -141,27 +202,7 @@ class DocumentationFile
     }
 
     /**
-     * Get main information from a .rst file
-     *
-     * @param string $file
-     * @return array
-     */
-    protected function getListEntry(string $file): array
-    {
-        $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
-        $headline = $this->extractHeadline($lines);
-        $entry['headline'] = $headline;
-        $entry['filepath'] = $file;
-        $entry['tags'] = $this->extractTags($lines);
-        $entry['tagList'] = implode(',', $entry['tags']);
-        $entry['content'] = file_get_contents($file);
-        $issueNumber = $this->extractIssueNumber($headline);
-
-        return [$issueNumber => $entry];
-    }
-
-    /**
-     * True if files within directory should be considered
+     * True for real directories and a valid version
      *
      * @param string $versionDirectory
      * @param string $version
@@ -227,4 +268,28 @@ class DocumentationFile
     {
         return $this->tagsTotal;
     }
+
+    /**
+     * whether that file has been removed from users view
+     *
+     * @param string $filename
+     * @return bool
+     */
+    protected function isFileIgnoredByUsersChoice(string $filename): bool
+    {
+        $isFileIgnoredByUsersChoice = false;
+
+        $ignoredFiles = $this->registry->get('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles');
+        if (is_array($ignoredFiles)) {
+            foreach ($ignoredFiles as $filePath) {
+                if ($filePath !== null && strlen($filePath) > 0) {
+                    if (strpos($filePath, $filename) !== false) {
+                        $isFileIgnoredByUsersChoice = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return $isFileIgnoredByUsersChoice;
+    }
 }
diff --git a/typo3/sysext/install/Resources/Private/Partials/Action/Ajax/UpgradeAnalysis/ListDocumentation.html b/typo3/sysext/install/Resources/Private/Partials/Action/Ajax/UpgradeAnalysis/ListDocumentation.html
deleted file mode 100644 (file)
index 92af230..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
-         xmlns:f="http://xsd.helhum.io/ns/typo3/cms-fluid/master/ViewHelpers">
-<head>
-       <title>Partials: ListDocumentation</title>
-</head>
-<body>
-<f:section name="Main">
-       <f:for each="{files}" as="versionArray" key="version">
-               <f:if condition="{versionArray -> f:count()} > 0">
-                       <h2>{version}</h2>
-                       <div class="panel-group" role="tablist" aria-multiselectable="false">
-                               <f:for each="{versionArray}" as="fileArray" key="issueNumber">
-
-                                       <div class="panel panel-default upgrade_analysis_item_to_filter"
-                                                        data-item-tags="{fileArray.tagList}" id="heading{issueNumber}">
-                                               <div class="panel-heading" role="tab">
-                                                       <h3 class="panel-title">
-                                                               <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{issueNumber}" aria-expanded="true" aria-controls="collapse{issueNumber}" class="collapsed">
-                                                                       <span class="caret"></span>
-                                                                       <strong >
-                                                                               {fileArray.headline}</strong>
-                                                               </a>
-                                                       </h3>
-                                               </div>
-                                               <div id="collapse{issueNumber}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{issueNumber}">
-                                                       <pre>{fileArray.content}</pre>
-                                               </div>
-                                       </div>
-
-                               </f:for>
-                       </div>
-               </f:if>
-       </f:for>
-</f:section>
-</body>
-</html>
diff --git a/typo3/sysext/install/Resources/Private/Partials/Action/Tool/UpgradeAnalysis/ListDocumentation.html b/typo3/sysext/install/Resources/Private/Partials/Action/Tool/UpgradeAnalysis/ListDocumentation.html
new file mode 100644 (file)
index 0000000..1a385a0
--- /dev/null
@@ -0,0 +1,15 @@
+<f:section name="Main">
+    <f:for each="{files}" as="versionArray" key="version">
+        <f:if condition="{versionArray -> f:count()} > 0">
+            <h2>{version}</h2>
+            <div class="panel-group" role="tablist" aria-multiselectable="false">
+                <f:for each="{versionArray}" as="fileArray" key="issueNumber">
+
+                    <f:render partial="Action/Tool/UpgradeAnalysis/PanelItem" section="Main"
+                              arguments="{issueNumber:issueNumber, fileArray:fileArray}"/>
+
+                </f:for>
+            </div>
+        </f:if>
+    </f:for>
+</f:section>
diff --git a/typo3/sysext/install/Resources/Private/Partials/Action/Tool/UpgradeAnalysis/PanelItem.html b/typo3/sysext/install/Resources/Private/Partials/Action/Tool/UpgradeAnalysis/PanelItem.html
new file mode 100644 (file)
index 0000000..2a08336
--- /dev/null
@@ -0,0 +1,18 @@
+<f:section name="Main">
+    <div class="panel panel-default upgrade_analysis_item_to_filter"
+         data-item-tags="{fileArray.tagList}" id="heading{issueNumber}">
+        <div class="panel-heading" role="tab">
+            <input type="checkbox" class="t3js-upgradeanalysis-ignore pull-left" data-filepath="{fileArray.filepath}" title="ignore this document"/>
+            <h3 class="panel-title">
+                <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{issueNumber}" aria-expanded="true" aria-controls="collapse{issueNumber}" class="collapsed">
+                    <span class="caret"></span>
+                    <strong >
+                        {fileArray.headline}</strong>
+                </a>
+            </h3>
+        </div>
+        <div id="collapse{issueNumber}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{issueNumber}">
+            <pre>{fileArray.content}</pre>
+        </div>
+    </div>
+</f:section>
diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Ajax/FilterManager.html b/typo3/sysext/install/Resources/Private/Templates/Action/Ajax/FilterManager.html
new file mode 100644 (file)
index 0000000..c473a6b
--- /dev/null
@@ -0,0 +1,22 @@
+<div class="t3js-response">
+    <f:for each="{files}" as="file">
+        <div class="panel-group" role="tablist" aria-multiselectable="false">
+
+            <div class="panel panel-default">
+                <div class="panel-heading" role="tab">
+                    <input type="checkbox" class="t3js-upgradeanalysis-restore pull-left" data-filepath="{file}"
+                           title="restore this document"/>
+                    <h3 class="panel-title">
+                            <strong>
+                                {file}</strong>
+                    </h3>
+                </div>
+            </div>
+
+        </div>
+
+    </f:for>
+    <h2>Files Restored (will be in their original section upon next call of this page)</h2>
+    <div class="panel-group" id="upgrade_analysis_restored_files" role="tablist" aria-multiselectable="false">
+    </div>
+</div>
diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Ajax/RemoveIgnoredItems.html b/typo3/sysext/install/Resources/Private/Templates/Action/Ajax/RemoveIgnoredItems.html
new file mode 100644 (file)
index 0000000..ecd7f73
--- /dev/null
@@ -0,0 +1 @@
+<f:render partial="Action/Tool/UpgradeAnalysis/PanelItem" section="Main" arguments="{issueNumber:issueNumber, fileArray:fileArray}" />
index 441f3fb..4d4ec83 100644 (file)
@@ -1,19 +1,18 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en"
-                       xmlns:f="http://xsd.helhum.io/ns/typo3/cms-fluid/master/ViewHelpers">
-<head>
-       <title>Template: Action/Tool/UpgradeAnalysis</title>
-</head>
-<body>
 <f:layout name="ToolAuthenticated"/>
 
 <f:section name="Content">
        <h1>Upgrade Analysis</h1>
 
+       <div class="btn-toolbar" role="toolbar" aria-label="Button Bar">
+               <div class="btn-group mr-2" role="group">
+                       <button type="button" id="t3js-showFilterManager" class="btn btn-default">Show Filter Manager</button>
+               </div>
+       </div>
+       <div class="t3js-filterManager"></div>
        <div id="tagsort_tags_container"></div>
        <div id="upgradeAnalysis_output">
-               <f:render partial="Action/Ajax/UpgradeAnalysis/ListDocumentation" section="Main" arguments="{_all}"/>
+               <f:render partial="Action/Tool/UpgradeAnalysis/ListDocumentation" section="Main" arguments="{_all}"/>
        </div>
+       <span id="saveIgnoredItemsToken" style="display:none;">{saveIgnoredItemsToken}</span>
+       <span id="removeIgnoredItemsToken" style="display:none;">{removeIgnoredItemsToken}</span>
 </f:section>
-</body>
-</html>
index 4d6fa81..9ecd1df 100644 (file)
@@ -895,17 +895,90 @@ $(function() {
        });
 
        TYPO3.Install.upgradeAnalysis.initialize();
-});
 
+       TYPO3.Install.upgradeAnalysis.showFilterManager();
+
+       TYPO3.Install.upgradeAnalysis.hideDoumentationFile();
+       TYPO3.Install.upgradeAnalysis.restoreDocumentationFile();
+});
 
 TYPO3.Install.upgradeAnalysis = {
-       provideTags: function() {
+       provideTags: function () {
                $('#tagsort_tags_container').tagSort({
                        selector: '.upgrade_analysis_item_to_filter'
                });
        },
 
-       initialize: function() {
+       initialize: function () {
                TYPO3.Install.upgradeAnalysis.provideTags();
+       },
+
+       showFilterManager: function () {
+               $(document).on('click', '#t3js-showFilterManager', function () {
+                       console.log('click!');
+                       var classOpen = 'display_open';
+                       if ($('#t3js-showFilterManager').hasClass(classOpen)) {
+                               $('#t3js-showFilterManager').removeClass(classOpen);
+                               $('.t3js-filterManager').html('');
+                       } else {
+                               $.ajax({
+                                       url: location.href + '&install[controller]=ajax&install[action]=filterManager',
+                                       cache: false,
+                                       success: function (res) {
+                                               var result = $(res).html();
+                                               $('.t3js-filterManager').html(result);
+                                               $('#t3js-showFilterManager').addClass(classOpen);
+                                       }
+                               });
+                       }
+               });
+       },
+
+       hideDoumentationFile: function () {
+               $(document).on('change', '.t3js-upgradeanalysis-ignore', function () {
+                       var filepath = $(this).data('filepath');
+                       if (this.checked) {
+                               var token = $('#saveIgnoredItemsToken').html();
+                               $(this).closest('.panel').fadeOut();
+                               var postData = {
+                                       'install': {
+                                               'ignoreFile': filepath,
+                                               'token': token,
+                                               'action': 'saveIgnoredItems'
+                                       }
+                               };
+                               $.ajax({
+                                       method: 'POST',
+                                       data: postData,
+                                       url: location.href + '&install[controller]=ajax'
+                               });
+                       }
+               });
+       },
+
+       restoreDocumentationFile: function () {
+               $(document).on('change', '.t3js-upgradeanalysis-restore', function () {
+                       var filepath = $(this).data('filepath');
+                       if (this.checked) {
+                               var token = $('#removeIgnoredItemsToken').html();
+                               $(this).closest('.panel').fadeOut();
+                               var postData = {
+                                       'install': {
+                                               'ignoreFile': filepath,
+                                               'token': token,
+                                               'action': 'removeIgnoredItems'
+                                       }
+                               };
+                               $.ajax({
+                                       method: 'POST',
+                                       data: postData,
+                                       url: location.href + '&install[controller]=ajax',
+                                       success: function (res) {
+                                               // append to restored panel
+                                               $('#upgrade_analysis_restored_files').append(res);
+                                       }
+                               });
+                       }
+               });
        }
 };
index 4562ce6..cf49ead 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 declare(strict_types=1);
+
 namespace TYPO3\CMS\Install\Tests\Unit\UpgradeAnalysis;
 
 /*
@@ -17,11 +18,12 @@ namespace TYPO3\CMS\Install\Tests\Unit\UpgradeAnalysis;
 
 use org\bovigo\vfs\vfsStream;
 use org\bovigo\vfs\vfsStreamDirectory;
+use Prophecy\Argument;
+use TYPO3\CMS\Core\Registry;
 use TYPO3\CMS\Install\UpgradeAnalysis\DocumentationFile;
 
 class DocumentationFileTest extends \TYPO3\Components\TestingFramework\Core\Unit\UnitTestCase
 {
-
     /**
      * @var DocumentationFile
      */
@@ -33,6 +35,11 @@ class DocumentationFileTest extends \TYPO3\Components\TestingFramework\Core\Unit
     protected $docRoot;
 
     /**
+     * @var Registry
+     */
+    protected $registry;
+
+    /**
      * set up test environment
      */
     public function setUp()
@@ -87,7 +94,41 @@ class DocumentationFileTest extends \TYPO3\Components\TestingFramework\Core\Unit
         ];
 
         $this->docRoot = vfsStream::setup('root', null, $structure);
-        $this->documentationFileService = new DocumentationFile();
+
+        $this->registry = $this->prophesize(Registry::class);
+        $this->documentationFileService = new DocumentationFile($this->registry->reveal(),
+            vfsStream::url('root/Changelog'));
+    }
+
+    /**
+     * dataprovider with invalid dir path. They should raise an exception and don't process.
+     * @return array
+     */
+    public function invalidDirProvider()
+    {
+        return [
+            [
+                'root' => '/'
+            ],
+            [
+                'etc' => '/etc'
+            ],
+            [
+                'etc/passwd' => '/etc/passwd'
+            ],
+        ];
+    }
+
+    /**
+     * @dataProvider invalidDirProvider
+     * @test
+     */
+    public function findDocumentationFilesThrowsExceptionIfPathIsNotInGivenChangelogDir(string $path)
+    {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionCode(1485425530);
+        $documentationFileService = new DocumentationFile($this->registry->reveal());
+        $documentationFileService->findDocumentationFiles($path);
     }
 
     /**
@@ -117,4 +158,40 @@ class DocumentationFileTest extends \TYPO3\Components\TestingFramework\Core\Unit
         $result = $this->documentationFileService->findDocumentationFiles(vfsStream::url('root/Changelog'));
         self::assertEquals($expected, $result['2.0'][98574]['tags']);
     }
+
+    /**
+     * @test
+     */
+    public function filesAreFilteredByUsersChoice()
+    {
+        $ignoredFiles = ['vfs://root/Changelog/1.2/Breaking-12345-Issue.rst'];
+        $this->registry->get('upgradeAnalysisIgnoreFilter', 'ignoredDocumentationFiles',
+            Argument::any())->willReturn($ignoredFiles);
+
+        $result = $this->documentationFileService->findDocumentationFiles(vfsStream::url('root/Changelog'));
+        self::assertArrayNotHasKey(12345, $result['1.2']);
+    }
+
+    /**
+     * @return array
+     */
+    public function invalidFilesProvider(): array
+    {
+        return [
+            ['/etc/passwd' => '/etc/passwd'],
+            ['root' => '/'],
+        ];
+    }
+
+    /**
+     * @dataProvider invalidFilesProvider
+     * @param string $path
+     * @test
+     */
+    public function getListEntryThrowsExceptionForFilesNotBelongToChangelogDir(string $path)
+    {
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionCode(1485425531);
+        $this->documentationFileService->getListEntry($path);
+    }
 }