[FEATURE] Report links to disabled linkhandler records 03/26503/9
authorAlexander Stehlik <alexander.stehlik@gmail.com>
Wed, 19 Nov 2014 18:02:14 +0000 (19:02 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Wed, 19 Nov 2014 18:17:12 +0000 (19:17 +0100)
A new TSConfig setting is introduced to mod.linkvalidator that is called
linkhandler.reportHiddenRecords.

If this setting is enabled an error will be triggerd in the linkhandler
link checker if a linked record is not enabled.

Resolves: #54519
Releases: master
Change-Id: Ib95cff1f9bdc67b0636cf38e6d9f33a8cbbdff75
Reviewed-on: http://review.typo3.org/26503
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/core/Documentation/Changelog/master/Feature-54519-CheckDisabledLinkhandlerRecords.rst [new file with mode: 0644]
typo3/sysext/linkvalidator/Classes/Linktype/LinkHandler.php
typo3/sysext/linkvalidator/Configuration/TsConfig/Page/pagetsconfig.txt
typo3/sysext/linkvalidator/Resources/Private/Language/Module/locallang.xlf

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-54519-CheckDisabledLinkhandlerRecords.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-54519-CheckDisabledLinkhandlerRecords.rst
new file mode 100644 (file)
index 0000000..6881119
--- /dev/null
@@ -0,0 +1,26 @@
+==============================================================
+Feature: #54519 - Report links to disabled linkhandler records
+==============================================================
+
+Description
+===========
+
+A new configuration option is introduced for the linkhandler link checker
+in the linkvalidator extension:
+
+.. code-block:: typoscript
+
+       mod.linkvalidator.linkhandler.reportHiddenRecords = 1
+
+..
+
+When this setting is enabled links will be considered invalid, when they
+point to disabled records. By default only links to deleted records are
+reported.
+
+Impact
+======
+
+The `\TYPO3\CMS\Linkvalidator\Linktype::checkLink()` method is restructured
+and will now determine if the linked record is deleted or hidden and report
+an error depending on the `reportHiddenRecords` configuration.
\ No newline at end of file
index 6c366c5..642e934 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Linkvalidator\Linktype;
  * The TYPO3 project - inspiring people to share!
  */
 
+use \TYPO3\CMS\Backend\Utility\BackendUtility;
+
 /**
  * This class provides Check Link Handler plugin implementation
  *
@@ -28,6 +30,20 @@ class LinkHandler extends \TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype {
        const DELETED = 'deleted';
 
        /**
+        * @var string
+        */
+       const DISABLED = 'disabled';
+
+       /**
+        * If this is TRUE an error will also be reported if the linked record
+        * is disabled. Otherwise the error will only be reported if the
+        * record is deleted or does not exist.
+        *
+        * @var boolean
+        */
+       protected $reportHiddenRecords;
+
+       /**
         * Checks a given URL for validity
         *
         * @param string $url Url to check
@@ -37,29 +53,56 @@ class LinkHandler extends \TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype {
         */
        public function checkLink($url, $softRefEntry, $reference) {
                $response = TRUE;
+               $errorType = '';
                $errorParams = array();
                $parts = explode(':', $url);
-               if (count($parts) == 3) {
-                       $tableName = htmlspecialchars($parts[1]);
-                       $rowid = (int)$parts[2];
-                       $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $tableName, 'uid = ' . (int)$rowid);
-                       if ($row) {
-                               if ($row['deleted'] == '1') {
-                                       $errorParams['errorType'] = self::DELETED;
-                                       $errorParams['tablename'] = $tableName;
-                                       $errorParams['uid'] = $rowid;
-                                       $response = FALSE;
-                               }
-                       } else {
-                               $errorParams['tablename'] = $tableName;
-                               $errorParams['uid'] = $rowid;
+               if (count($parts) !== 3) {
+                       return $response;
+               }
+
+               $tableName = htmlspecialchars($parts[1]);
+               $rowid = (int)$parts[2];
+               $row = NULL;
+               $tsConfig = $reference->getTSConfig();
+               $reportHiddenRecords = (bool)$tsConfig['linkhandler.']['reportHiddenRecords'];
+
+               // First check, if we find a non disabled record if the check
+               // for hidden records is enabled.
+               if ($reportHiddenRecords) {
+                       $row = $this->getRecordRow($tableName, $rowid, 'disabled');
+                       if ($row === NULL) {
+                               $response = FALSE;
+                               $errorType = self::DISABLED;
+                       }
+               }
+
+               // If no enabled record was found or we did not check that see
+               // if we can find a non deleted record.
+               if ($row === NULL) {
+                       $row = $this->getRecordRow($tableName, $rowid, 'deleted');
+                       if ($row === NULL) {
                                $response = FALSE;
+                               $errorType = self::DELETED;
+                       }
+               }
+
+               // If we did not find a non deleted record, check if we find a
+               // deleted one.
+               if ($row === NULL) {
+                       $row = $this->getRecordRow($tableName, $rowid, 'all');
+                       if ($row === NULL) {
+                               $response = FALSE;
+                               $errorType = '';
                        }
                }
 
                if (!$response) {
+                       $errorParams['errorType'] = $errorType;
+                       $errorParams['tablename'] = $tableName;
+                       $errorParams['uid'] = $rowid;
                        $this->setErrorParams($errorParams);
                }
+
                return $response;
        }
 
@@ -93,6 +136,11 @@ class LinkHandler extends \TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype {
                        $title = $tableName;
                }
                switch ($errorType) {
+                       case self::DISABLED:
+                               $response = $GLOBALS['LANG']->getLL('list.report.rownotvisible');
+                               $response = str_replace('###title###', $title, $response);
+                               $response = str_replace('###uid###', $errorParams['uid'], $response);
+                               break;
                        case self::DELETED:
                                $response = str_replace(
                                        array(
@@ -111,4 +159,53 @@ class LinkHandler extends \TYPO3\CMS\Linkvalidator\Linktype\AbstractLinktype {
                }
                return $response;
        }
+
+       /**
+        * Fetches the record with the given UID from the given table.
+        *
+        * The filter option accepts two values:
+        *
+        * "disabled" will filter out disabled and deleted records.
+        * "deleted" filters out deleted records but will return disabled records.
+        * If nothing is specified all records will be returned (including deleted).
+        *
+        * @param string $tableName The name of the table from which the record should be fetched.
+        * @param string $uid The UID of the record that should be fetched.
+        * @param string $filter A filter setting, can be empty or "disabled" or "deleted".
+        * @return array|NULL The result row as associative array or NULL if nothing is found.
+        */
+       protected function getRecordRow($tableName, $uid, $filter = '') {
+
+               $whereStatement = 'uid = ' . (int)$uid;
+
+               switch ($filter) {
+                       case 'disabled':
+                               $whereStatement .= BackendUtility::BEenableFields($tableName) . BackendUtility::deleteClause($tableName);
+                               break;
+                       case 'deleted':
+                               $whereStatement .= BackendUtility::deleteClause($tableName);
+                               break;
+               }
+
+               $row = $this->getDatabaseConnection()->exec_SELECTgetSingleRow(
+                       '*',
+                       $tableName,
+                       $whereStatement
+               );
+
+               // Since exec_SELECTgetSingleRow can return NULL or FALSE we
+               // make sure we always return NULL if no row was found.
+               if ($row === FALSE) {
+                       $row = NULL;
+               }
+
+               return $row;
+       }
+
+       /**
+        * @return \TYPO3\CMS\Core\Database\DatabaseConnection
+        */
+       protected function getDatabaseConnection() {
+               return $GLOBALS['TYPO3_DB'];
+       }
 }
index 7875e01..edb3fea 100644 (file)
@@ -14,4 +14,5 @@ mod.linkvalidator {
                replytoemail =
                subject = TYPO3 Linkvalidator report
        }
+       linkhandler.reportHiddenRecords = 0
 }
\ No newline at end of file
index 4dcfc7d..a8e7968 100644 (file)
                        <trans-unit id="list.report.contentnotexisting" xml:space="preserve">
                                <source>Element (###uid###) does not exist.</source>
                        </trans-unit>
+                       <trans-unit id="list.report.rownotvisible" xml:space="preserve">
+                               <source>###title### row (###uid###) is not visible.</source>
+                       </trans-unit>
                        <trans-unit id="list.report.rowdeleted" xml:space="preserve">
                                <source>###title### row (###uid###) is deleted.</source>
                        </trans-unit>