[TASK] Cleanup phpDoc to match CGL
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Service / AbstractService.php
1 <?php
2 namespace TYPO3\CMS\Core\Service;
3
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 */
16
17 /**
18 * Parent class for "Services" classes
19 *
20 * @author René Fritz <r.fritz@colorcube.de>
21 */
22 abstract class AbstractService {
23
24 /**
25 * @var array service description array
26 */
27 public $info = array();
28
29 /**
30 * @var array error stack
31 */
32 public $error = array();
33
34 /**
35 * @var bool Defines if debug messages should be written with \TYPO3\CMS\Core\Utility\GeneralUtility::devLog
36 */
37 public $writeDevLog = FALSE;
38
39 /**
40 * @var string The output content. That's what the services produced as result.
41 */
42 public $out = '';
43
44 /**
45 * @var string The file that should be processed.
46 */
47 public $inputFile = '';
48
49 /**
50 * @var string The content that should be processed.
51 */
52 public $inputContent = '';
53
54 /**
55 * @var string The type of the input content (or file). Might be the same as the service subtypes.
56 */
57 public $inputType = '';
58
59 /**
60 * @var string The file where the output should be written to.
61 */
62 public $outputFile = '';
63
64 /**
65 * Temporary files which have to be deleted
66 *
67 * @private
68 * @var array
69 */
70 public $tempFiles = array();
71
72 /**
73 * @var array list of registered shutdown functions; should be used to prevent registering the same function multiple times
74 */
75 protected $shutdownRegistry = array();
76
77 /**
78 * @var string Prefix for temporary files
79 */
80 protected $prefixId = '';
81
82 /***************************************
83 *
84 * Get service meta information
85 *
86 ***************************************/
87 /**
88 * Returns internal information array for service
89 *
90 * @return array Service description array
91 */
92 public function getServiceInfo() {
93 return $this->info;
94 }
95
96 /**
97 * Returns the service key of the service
98 *
99 * @return string Service key
100 */
101 public function getServiceKey() {
102 return $this->info['serviceKey'];
103 }
104
105 /**
106 * Returns the title of the service
107 *
108 * @return string Service title
109 */
110 public function getServiceTitle() {
111 return $this->info['title'];
112 }
113
114 /**
115 * Returns service configuration values from the $TYPO3_CONF_VARS['SVCONF'] array
116 *
117 * @param string $optionName Name of the config option
118 * @param mixed $defaultValue Default configuration if no special config is available
119 * @param bool $includeDefaultConfig If set the 'default' config will be returned if no special config for this service is available (default: TRUE)
120 * @return mixed Configuration value for the service
121 */
122 public function getServiceOption($optionName, $defaultValue = '', $includeDefaultConfig = TRUE) {
123 $config = NULL;
124 $svOptions = $GLOBALS['TYPO3_CONF_VARS']['SVCONF'][$this->info['serviceType']];
125 if (isset($svOptions[$this->info['serviceKey']][$optionName])) {
126 $config = $svOptions[$this->info['serviceKey']][$optionName];
127 } elseif ($includeDefaultConfig && isset($svOptions['default'][$optionName])) {
128 $config = $svOptions['default'][$optionName];
129 }
130 if (!isset($config)) {
131 $config = $defaultValue;
132 }
133 return $config;
134 }
135
136 /***************************************
137 *
138 * Error handling
139 *
140 ***************************************/
141 /**
142 * Logs debug messages to \TYPO3\CMS\Core\Utility\GeneralUtility::devLog()
143 *
144 * @param string $msg Debug message
145 * @param int $severity Severity: 0 is info, 1 is notice, 2 is warning, 3 is fatal error, -1 is "OK" message
146 * @param array|bool $dataVar dditional data you want to pass to the logger.
147 * @return void
148 */
149 public function devLog($msg, $severity = 0, $dataVar = FALSE) {
150 if ($this->writeDevLog) {
151 \TYPO3\CMS\Core\Utility\GeneralUtility::devLog($msg, $this->info['serviceKey'], $severity, $dataVar);
152 }
153 }
154
155 /**
156 * Puts an error on the error stack. Calling without parameter adds a general error.
157 *
158 * @param int $errNum Error number (see T3_ERR_SV_* constants)
159 * @param string $errMsg Error message
160 * @return void
161 */
162 public function errorPush($errNum = T3_ERR_SV_GENERAL, $errMsg = 'Unspecified error occurred') {
163 array_push($this->error, array('nr' => $errNum, 'msg' => $errMsg));
164 if (is_object($GLOBALS['TT'])) {
165 $GLOBALS['TT']->setTSlogMessage($errMsg, 2);
166 }
167 }
168
169 /**
170 * Removes the last error from the error stack.
171 *
172 * @return void
173 */
174 public function errorPull() {
175 array_pop($this->error);
176 }
177
178 /**
179 * Returns the last error number from the error stack.
180 *
181 * @return int|bool Error number (or TRUE if no error)
182 */
183 public function getLastError() {
184 // Means all is ok - no error
185 $lastError = TRUE;
186 if (count($this->error)) {
187 $error = end($this->error);
188 $lastError = $error['nr'];
189 }
190 return $lastError;
191 }
192
193 /**
194 * Returns the last message from the error stack.
195 *
196 * @return string Error message
197 */
198 public function getLastErrorMsg() {
199 $lastErrorMessage = '';
200 if (count($this->error)) {
201 $error = end($this->error);
202 $lastErrorMessage = $error['msg'];
203 }
204 return $lastErrorMessage;
205 }
206
207 /**
208 * Returns all error messages as array.
209 *
210 * @return array Error messages
211 */
212 public function getErrorMsgArray() {
213 $errArr = array();
214 if (count($this->error)) {
215 foreach ($this->error as $error) {
216 $errArr[] = $error['msg'];
217 }
218 }
219 return $errArr;
220 }
221
222 /**
223 * Returns the last array from the error stack.
224 *
225 * @return array Error number and message
226 */
227 public function getLastErrorArray() {
228 return end($this->error);
229 }
230
231 /**
232 * Reset the error stack.
233 *
234 * @return void
235 */
236 public function resetErrors() {
237 $this->error = array();
238 }
239
240 /***************************************
241 *
242 * General service functions
243 *
244 ***************************************/
245 /**
246 * check the availability of external programs
247 *
248 * @param string $progList Comma list of programs 'perl,python,pdftotext'
249 * @return bool Return FALSE if one program was not found
250 */
251 public function checkExec($progList) {
252 $ret = TRUE;
253 $progList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $progList, TRUE);
254 foreach ($progList as $prog) {
255 if (!\TYPO3\CMS\Core\Utility\CommandUtility::checkCommand($prog)) {
256 // Program not found
257 $this->errorPush(T3_ERR_SV_PROG_NOT_FOUND, 'External program not found: ' . $prog);
258 $ret = FALSE;
259 }
260 }
261 return $ret;
262 }
263
264 /**
265 * Deactivate the service. Use this if the service fails at runtime and will not be available.
266 *
267 * @return void
268 */
269 public function deactivateService() {
270 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::deactivateService($this->info['serviceType'], $this->info['serviceKey']);
271 }
272
273 /***************************************
274 *
275 * IO tools
276 *
277 ***************************************/
278 /**
279 * Check if a file exists and is readable.
280 *
281 * @param string $absFile File name with absolute path.
282 * @return string|boolean File name or FALSE.
283 */
284 public function checkInputFile($absFile) {
285 $checkResult = FALSE;
286 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($absFile) && @is_file($absFile)) {
287 if (@is_readable($absFile)) {
288 $checkResult = $absFile;
289 } else {
290 $this->errorPush(T3_ERR_SV_FILE_READ, 'File is not readable: ' . $absFile);
291 }
292 } else {
293 $this->errorPush(T3_ERR_SV_FILE_NOT_FOUND, 'File not found: ' . $absFile);
294 }
295 return $checkResult;
296 }
297
298 /**
299 * Read content from a file a file.
300 *
301 * @param string $absFile File name to read from.
302 * @param int $length Maximum length to read. If empty the whole file will be read.
303 * @return string|boolean $content or FALSE
304 */
305 public function readFile($absFile, $length = 0) {
306 $out = FALSE;
307 if ($this->checkInputFile($absFile)) {
308 $out = file_get_contents($absFile);
309 if ($out === FALSE) {
310 $this->errorPush(T3_ERR_SV_FILE_READ, 'Can not read from file: ' . $absFile);
311 }
312 }
313 return $out;
314 }
315
316 /**
317 * Write content to a file.
318 *
319 * @param string $content Content to write to the file
320 * @param string $absFile File name to write into. If empty a temp file will be created.
321 * @return string|boolean File name or FALSE
322 */
323 public function writeFile($content, $absFile = '') {
324 if (!$absFile) {
325 $absFile = $this->tempFile($this->prefixId);
326 }
327 if ($absFile && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($absFile)) {
328 if ($fd = @fopen($absFile, 'wb')) {
329 @fwrite($fd, $content);
330 @fclose($fd);
331 } else {
332 $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not write to file: ' . $absFile);
333 $absFile = FALSE;
334 }
335 }
336 return $absFile;
337 }
338
339 /**
340 * Create a temporary file.
341 *
342 * @param string $filePrefix File prefix.
343 * @return string|boolean File name or FALSE
344 */
345 public function tempFile($filePrefix) {
346 $absFile = \TYPO3\CMS\Core\Utility\GeneralUtility::tempnam($filePrefix);
347 if ($absFile) {
348 $ret = $absFile;
349 $this->registerTempFile($absFile);
350 } else {
351 $ret = FALSE;
352 $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not create temp file.');
353 }
354 return $ret;
355 }
356
357 /**
358 * Register file which should be deleted afterwards.
359 *
360 * @param string File name with absolute path.
361 * @return void
362 */
363 public function registerTempFile($absFile) {
364 if (!isset($this->shutdownRegistry[__METHOD__])) {
365 register_shutdown_function(array($this, 'unlinkTempFiles'));
366 $this->shutdownRegistry[__METHOD__] = TRUE;
367 }
368 $this->tempFiles[] = $absFile;
369 }
370
371 /**
372 * Delete registered temporary files.
373 *
374 * @return void
375 */
376 public function unlinkTempFiles() {
377 foreach ($this->tempFiles as $absFile) {
378 \TYPO3\CMS\Core\Utility\GeneralUtility::unlink_tempfile($absFile);
379 }
380 $this->tempFiles = array();
381 }
382
383 /***************************************
384 *
385 * IO input
386 *
387 ***************************************/
388 /**
389 * Set the input content for service processing.
390 *
391 * @param mixed $content Input content (going into ->inputContent)
392 * @param string $type The type of the input content (or file). Might be the same as the service subtypes.
393 * @return void
394 */
395 public function setInput($content, $type = '') {
396 $this->inputContent = $content;
397 $this->inputFile = '';
398 $this->inputType = $type;
399 }
400
401 /**
402 * Set the input file name for service processing.
403 *
404 * @param string $absFile File name
405 * @param string $type The type of the input content (or file). Might be the same as the service subtypes.
406 * @return void
407 */
408 public function setInputFile($absFile, $type = '') {
409 $this->inputContent = '';
410 $this->inputFile = $absFile;
411 $this->inputType = $type;
412 }
413
414 /**
415 * Get the input content.
416 * Will be read from input file if needed. (That is if ->inputContent is empty and ->inputFile is not)
417 *
418 * @return mixed
419 */
420 public function getInput() {
421 if ($this->inputContent == '') {
422 $this->inputContent = $this->readFile($this->inputFile);
423 }
424 return $this->inputContent;
425 }
426
427 /**
428 * Get the input file name.
429 * If the content was set by setContent a file will be created.
430 *
431 * @param string $createFile File name. If empty a temp file will be created.
432 * @return string File name or FALSE if no input or file error.
433 */
434 public function getInputFile($createFile = '') {
435 if ($this->inputFile) {
436 $this->inputFile = $this->checkInputFile($this->inputFile);
437 } elseif ($this->inputContent) {
438 $this->inputFile = $this->writeFile($this->inputContent, $createFile);
439 }
440 return $this->inputFile;
441 }
442
443 /***************************************
444 *
445 * IO output
446 *
447 ***************************************/
448 /**
449 * Set the output file name.
450 *
451 * @param string $absFile File name
452 * @return void
453 */
454 public function setOutputFile($absFile) {
455 $this->outputFile = $absFile;
456 }
457
458 /**
459 * Get the output content.
460 *
461 * @return mixed
462 */
463 public function getOutput() {
464 if ($this->outputFile) {
465 $this->out = $this->readFile($this->outputFile);
466 }
467 return $this->out;
468 }
469
470 /**
471 * Get the output file name. If no output file is set, the ->out buffer is written to the file given by input parameter filename
472 *
473 * @param string $absFile Absolute filename to write to
474 * @return mixed
475 */
476 public function getOutputFile($absFile = '') {
477 if (!$this->outputFile) {
478 $this->outputFile = $this->writeFile($this->out, $absFile);
479 }
480 return $this->outputFile;
481 }
482
483 /***************************************
484 *
485 * Service implementation
486 *
487 ***************************************/
488 /**
489 * Initialization of the service.
490 *
491 * The class have to do a strict check if the service is available.
492 * example: check if the perl interpreter is available which is needed to run an extern perl script.
493 *
494 * @return bool TRUE if the service is available
495 */
496 public function init() {
497 // look in makeInstanceService()
498 $this->reset();
499 // Check for external programs which are defined by $info['exec']
500 if (trim($this->info['exec'])) {
501 if (!$this->checkExec($this->info['exec'])) {
502
503 }
504 }
505 return $this->getLastError() === TRUE;
506 }
507
508 /**
509 * Resets the service.
510 * Will be called by init(). Should be used before every use if a service instance is used multiple times.
511 *
512 * @return void
513 */
514 public function reset() {
515 $this->unlinkTempFiles();
516 $this->resetErrors();
517 $this->out = '';
518 $this->inputFile = '';
519 $this->inputContent = '';
520 $this->inputType = '';
521 $this->outputFile = '';
522 }
523
524 /**
525 * Clean up the service.
526 * Child classes should explicitly call parent::__destruct() in their destructors for this to work
527 *
528 * @return void
529 */
530 public function __destruct() {
531 $this->unlinkTempFiles();
532 }
533
534 }