11<?php
2- namespace Aoe \Linkhandler \Linkvalidator ;
2+ namespace Cobweb \Linkhandler \Linkvalidator ;
33
4- /* *
5- * This script belongs to the TYPO3 extension "linkhandler". *
6- * *
7- * It is free software; you can redistribute it and/or modify it under *
8- * the terms of the GNU General Public License as published by the Free *
9- * Software Foundation, either version 3 of the License, or (at your *
10- * option) any later version. *
11- * *
12- * This script is distributed in the hope that it will be useful, but *
13- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14- * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
15- * Public License for more details. *
16- * *
17- * You should have received a copy of the GNU General Public License *
18- * along with the script. *
19- * If not, see http://www.gnu.org/licenses/gpl.html *
20- * *
21- * The TYPO3 project - inspiring people to share! *
22- * */
4+ /*
5+ * This file is part of the TYPO3 CMS project.
6+ *
7+ * It is free software; you can redistribute it and/or modify it under
8+ * the terms of the GNU General Public License, either version 2
9+ * of the License, or any later version.
10+ *
11+ * For the full copyright and license information, please read the
12+ * LICENSE.txt file that was distributed with this source code.
13+ *
14+ * The TYPO3 project - inspiring people to share!
15+ */
2316
17+ use Cobweb \Linkhandler \Domain \Model \RecordLink ;
2418use TYPO3 \CMS \Linkvalidator \Linktype \AbstractLinktype ;
2519use TYPO3 \CMS \Backend \Utility \BackendUtility ;
2620
@@ -44,6 +38,20 @@ class LinkhandlerLinkType extends AbstractLinktype
4438 */
4539 const ERROR_TYPE_DISABLED = 'disabled ' ;
4640
41+ /**
42+ * This error occurs when the related record does not exist at all.
43+ *
44+ * @var string
45+ */
46+ const ERROR_TYPE_MISSING = 'missing ' ;
47+
48+ /**
49+ * This error occurs when the related record does not exist at all.
50+ *
51+ * @var string
52+ */
53+ const ERROR_TYPE_INVALID = 'invalid ' ;
54+
4755 /**
4856 * TYPO3 database connection.
4957 *
@@ -66,89 +74,90 @@ class LinkhandlerLinkType extends AbstractLinktype
6674 protected $ languageService ;
6775
6876 /**
69- * If this is TRUE an error will also be reported if the linked record
70- * is disabled. Otherwise the error will only be reported if the
71- * record is deleted or does not exist.
72- *
73- * @var boolean
74- */
75- protected $ reportHiddenRecords ;
76-
77- /**
78- * Tab handler factory for retrieving link information.
79- *
80- * @var \Aoe\Linkhandler\Browser\TabHandlerFactory
77+ * @var RecordLink
8178 */
82- protected $ tabHandlerFactory ;
79+ protected $ recordLink ;
8380
8481 /**
85- * Checks a given URL for validity
82+ * Checks a given URL for validity.
8683 *
8784 * @param string $url Url to check
8885 * @param array $softRefEntry The soft reference entry which builds the context of that url
89- * @param \TYPO3\CMS\Linkvalidator\LinkAnalyzer $reference Parent instance
86+ * @param \TYPO3\CMS\Linkvalidator\LinkAnalyzer $linkAnalyzer Parent instance
9087 * @return boolean TRUE on success or FALSE on error
9188 */
92- public function checkLink ($ url , $ softRefEntry , $ reference )
89+ public function checkLink ($ url , $ softRefEntry , $ linkAnalyzer )
9390 {
9491 $ response = true ;
9592 $ errorType = '' ;
9693 $ errorParams = array ();
9794 $ this ->initializeRequiredClasses ();
9895
99- $ linkInfo = $ this ->tabHandlerFactory ->getLinkInfoArrayFromMatchingHandler ($ url );
100- if (empty ($ linkInfo )) {
101- return true ;
96+ try {
97+ $ this ->recordLink = \TYPO3 \CMS \Core \Utility \GeneralUtility::makeInstance (
98+ RecordLink::class,
99+ $ url
100+ );
101+ }
102+ catch (\Exception $ e ) {
103+ // Set error type to invalid (record reference) and return early
104+ $ this ->setErrorParams (
105+ array (
106+ 'errorType ' => self ::ERROR_TYPE_INVALID ,
107+ 'url ' => $ url
108+ )
109+ );
110+ return false ;
102111 }
103112
104- $ tableName = $ linkInfo ['recordTable ' ];
105- $ rowid = $ linkInfo ['recordUid ' ];
106- $ row = null ;
107- $ tsConfig = $ reference ->getTSConfig ();
108- $ this ->reportHiddenRecords = (bool )$ tsConfig ['tx_linkhandler. ' ]['reportHiddenRecords ' ];
113+ // Get hidden records reporting parameter from TSconfig
114+ // If hidden records reporting is true, an error will be raised for hidden records and not just for deleted or missing records
115+ $ tsConfig = $ linkAnalyzer ->getTSConfig ();
116+ $ reportHiddenRecords = (bool )$ tsConfig ['tx_linkhandler. ' ]['reportHiddenRecords ' ];
109117
110- // First check, if we find a non disabled record if the check
111- // for hidden records is enabled.
112- if ($ this ->reportHiddenRecords ) {
113- $ row = $ this ->getRecordRow ($ tableName , $ rowid , 'disabled ' );
114- if ($ row === null ) {
115- $ response = false ;
116- $ errorType = self ::ERROR_TYPE_DISABLED ;
117- }
118+ // Get the record without enable fields
119+ // If reporting about "hidden" records, also get the record with enable fields
120+ $ rawRecord = $ this ->getRecordRow ();
121+ $ enabledRecord = $ rawRecord ;
122+ if ($ reportHiddenRecords ) {
123+ $ enabledRecord = $ this ->getRecordRow (true );
118124 }
119125
120- // If no enabled record was found or we did not check that see
121- // if we can find a non deleted record.
122- if ($ row === null ) {
123- $ row = $ this ->getRecordRow ($ tableName , $ rowid , 'deleted ' );
124- if ($ row === null ) {
125- $ response = false ;
126- $ errorType = self ::ERROR_TYPE_DELETED ;
126+ // If the record was not found without any condition, it is completely missing from the database
127+ if ($ rawRecord === null ) {
128+ $ response = false ;
129+ $ errorType = self ::ERROR_TYPE_MISSING ;
130+ } else {
131+ // If the record was found, but its "delete" flag is set, it is a deleted record
132+ $ deleteFlag = (!empty ($ GLOBALS ['TCA ' ][$ this ->recordLink ->getTable ()]['ctrl ' ]['delete ' ])) ? $ GLOBALS ['TCA ' ][$ this ->recordLink ->getTable ()]['ctrl ' ]['delete ' ] : '' ;
133+ if ($ deleteFlag !== '' ) {
134+ $ deleted = (bool )$ rawRecord [$ deleteFlag ];
135+ if ($ deleted ) {
136+ $ response = false ;
137+ $ errorType = self ::ERROR_TYPE_DELETED ;
138+ }
127139 }
128- }
129-
130- // If we did not find a non deleted record, check if we find a
131- // deleted one.
132- if ($ row === null ) {
133- $ row = $ this ->getRecordRow ($ tableName , $ rowid , 'all ' );
134- if ($ row === null ) {
140+ // If no record was fetched when applying the "enable fields" conditions, the record is currently disabled
141+ if ($ enabledRecord === null ) {
135142 $ response = false ;
136- $ errorType = '' ;
143+ $ errorType = self :: ERROR_TYPE_DISABLED ;
137144 }
138145 }
139146
140147 if (!$ response ) {
141148 $ errorParams ['errorType ' ] = $ errorType ;
142- $ errorParams ['tablename ' ] = $ tableName ;
143- $ errorParams ['uid ' ] = $ rowid ;
149+ $ errorParams ['tablename ' ] = $ this -> recordLink -> getTable () ;
150+ $ errorParams ['uid ' ] = $ this -> recordLink -> getId () ;
144151 $ this ->setErrorParams ($ errorParams );
145152 }
146153
147154 return $ response ;
148155 }
149156
150157 /**
151- * Type fetching method, based on the type that softRefParserObj returns
158+ * Returns the type of link.
159+ *
160+ * If we detect a link starting with "record:", we consider it to be one of "ours".
152161 *
153162 * @param array $value Reference properties
154163 * @param string $type Current type
@@ -164,7 +173,7 @@ public function fetchType($value, $type, $key)
164173 }
165174
166175 /**
167- * Generate the localized error message from the error params saved from the parsing
176+ * Generates the localized error message from the error params saved from the parsing.
168177 *
169178 * @param array $errorParams All parameters needed for the rendering of the error message
170179 * @return string Validation error message
@@ -173,55 +182,51 @@ public function getErrorMessage($errorParams)
173182 {
174183 $ this ->initializeRequiredClasses ();
175184 $ errorType = $ errorParams ['errorType ' ];
185+
186+ // For invalid reference, return early with simple error message
187+ if ($ errorType === self ::ERROR_TYPE_INVALID ) {
188+ return $ this ->translate ('list.report.invalidurl ' );
189+ }
190+
176191 $ tableName = $ errorParams ['tablename ' ];
177192 $ title = $ this ->translate ('list.report.rowdeleted.default.title ' );
178193 if ($ GLOBALS ['TCA ' ][$ tableName ]['ctrl ' ]['title ' ]) {
179194 $ title = $ this ->languageService ->sL ($ GLOBALS ['TCA ' ][$ tableName ]['ctrl ' ]['title ' ]);
180195 }
181196 switch ($ errorType ) {
182197 case self ::ERROR_TYPE_DISABLED :
183- $ response = $ this ->getTranslatedErrorMessage ('list.report.rownotvisible ' , $ errorParams ['uid ' ], $ title );
198+ $ message = $ this ->translate ('list.report.rownotvisible ' );
199+ $ response = sprintf ($ message , $ title , $ errorParams ['uid ' ]);
184200 break ;
185201 case self ::ERROR_TYPE_DELETED :
186- $ response = $ this ->getTranslatedErrorMessage ('list.report.rowdeleted ' , $ errorParams ['uid ' ], $ title );
202+ $ message = $ this ->translate ('list.report.rowdeleted ' );
203+ $ response = sprintf ($ message , $ title , $ errorParams ['uid ' ]);
187204 break ;
205+ // Default is missing record
188206 default :
189- $ response = $ this ->getTranslatedErrorMessage ('list.report.rownotexisting ' , $ errorParams ['uid ' ]);
207+ $ message = $ this ->translate ('list.report.rownotexisting ' );
208+ $ response = sprintf ($ message , $ title , $ errorParams ['uid ' ]);
190209 }
191210 return $ response ;
192211 }
193212
194213 /**
195- * Fetches the record with the given UID from the given table.
196- *
197- * The filter option accepts two values:
198- *
199- * "disabled" will filter out disabled and deleted records.
200- * "deleted" filters out deleted records but will return disabled records.
201- * If nothing is specified all records will be returned (including deleted).
214+ * Fetches the record corresponding to the current record reference.
202215 *
203- * @param string $tableName The name of the table from which the record should be fetched.
204- * @param string $uid The UID of the record that should be fetched.
205- * @param string $filter A filter setting, can be empty or "disabled" or "deleted".
216+ * @param bool $applyEnableFields TRUE to apply enable fields condition to
206217 * @return array The result row as associative array.
207218 */
208- protected function getRecordRow ($ tableName , $ uid , $ filter = '' )
219+ protected function getRecordRow ($ applyEnableFields = false )
209220 {
210221
211- $ whereStatement = 'uid = ' . (int )$ uid ;
212-
213- switch ($ filter ) {
214- case 'disabled ' :
215- $ whereStatement .= BackendUtility::BEenableFields ($ tableName ) . BackendUtility::deleteClause ($ tableName );
216- break ;
217- case 'deleted ' :
218- $ whereStatement .= BackendUtility::deleteClause ($ tableName );
219- break ;
222+ $ whereStatement = 'uid = ' . $ this ->recordLink ->getId ();
223+ if ($ applyEnableFields ) {
224+ $ whereStatement .= BackendUtility::BEenableFields ($ this ->recordLink ->getTable ());
220225 }
221226
222227 $ row = $ this ->databaseConnection ->exec_SELECTgetSingleRow (
223228 '* ' ,
224- $ tableName ,
229+ $ this -> recordLink -> getTable () ,
225230 $ whereStatement
226231 );
227232
@@ -253,14 +258,10 @@ protected function getTranslatedErrorMessage($translationKey, $uid, $title = nul
253258 }
254259
255260 /**
256- * Initializes all required classes if required .
261+ * Initializes all required classes.
257262 */
258263 protected function initializeRequiredClasses ()
259264 {
260- if (isset ($ this ->tabHandlerFactory )) {
261- return ;
262- }
263- $ this ->tabHandlerFactory = \TYPO3 \CMS \Core \Utility \GeneralUtility::makeInstance ('Aoe \\Linkhandler \\Browser \\TabHandlerFactory ' );
264265 $ this ->languageService = $ GLOBALS ['LANG ' ];
265266 $ this ->databaseConnection = $ GLOBALS ['TYPO3_DB ' ];
266267 }
0 commit comments