‪TYPO3CMS  9.5
ResourceCompressor.php
Go to the documentation of this file.
1 <?php
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 
21 
27 {
31  protected ‪$targetDirectory = 'typo3temp/assets/compressed/';
32 
36  protected ‪$rootPath = '';
37 
43  protected ‪$createGzipped = false;
44 
48  protected ‪$gzipCompressionLevel = -1;
49 
53  protected ‪$htaccessTemplate = '<FilesMatch "\\.(js|css)(\\.gzip)?$">
54  <IfModule mod_expires.c>
55  ExpiresActive on
56  ExpiresDefault "access plus 7 days"
57  </IfModule>
58  FileETag MTime Size
59 </FilesMatch>';
60 
64  public function ‪__construct()
65  {
66  // we check for existence of our targetDirectory
67  if (!is_dir(‪Environment::getPublicPath() . '/' . $this->targetDirectory)) {
68  GeneralUtility::mkdir_deep(‪Environment::getPublicPath() . '/' . $this->targetDirectory);
69  }
70  // if enabled, we check whether we should auto-create the .htaccess file
71  if (‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['generateApacheHtaccess']) {
72  // check whether .htaccess exists
73  $htaccessPath = ‪Environment::getPublicPath() . '/' . $this->targetDirectory . '.htaccess';
74  if (!file_exists($htaccessPath)) {
75  GeneralUtility::writeFile($htaccessPath, $this->htaccessTemplate);
76  }
77  }
78  // decide whether we should create gzipped versions or not
79  $compressionLevel = ‪$GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['compressionLevel'];
80  // we need zlib for gzencode()
81  if (extension_loaded('zlib') && $compressionLevel) {
82  $this->createGzipped = true;
83  // $compressionLevel can also be TRUE
84  if (‪MathUtility::canBeInterpretedAsInteger($compressionLevel)) {
85  $this->gzipCompressionLevel = (int)$compressionLevel;
86  }
87  }
88  $this->‪setRootPath(TYPO3_MODE === 'BE' ? ‪Environment::getBackendPath() . '/' : ‪Environment::getPublicPath() . '/');
89  }
90 
96  public function ‪setRootPath(‪$rootPath)
97  {
98  if (is_string(‪$rootPath)) {
99  $this->rootPath = ‪$rootPath;
100  }
101  }
102 
113  public function ‪concatenateCssFiles(array $cssFiles, array $options = [])
114  {
115  $filesToIncludeByType = ['all' => []];
116  foreach ($cssFiles as $key => $fileOptions) {
117  // no concatenation allowed for this file, so continue
118  if (!empty($fileOptions['excludeFromConcatenation'])) {
119  continue;
120  }
121  $filenameFromMainDir = $this->‪getFilenameFromMainDir($fileOptions['file']);
122  // if $options['baseDirectories'] set, we only include files below these directories
123  if (
124  !isset($options['baseDirectories'])
125  || $this->‪checkBaseDirectory(
126  $filenameFromMainDir,
127  array_merge($options['baseDirectories'], [$this->targetDirectory])
128  )
129  ) {
130  $type = isset($fileOptions['media']) ? strtolower($fileOptions['media']) : 'all';
131  if (!isset($filesToIncludeByType[$type])) {
132  $filesToIncludeByType[$type] = [];
133  }
134  if (!empty($fileOptions['forceOnTop'])) {
135  array_unshift($filesToIncludeByType[$type], $filenameFromMainDir);
136  } else {
137  $filesToIncludeByType[$type][] = $filenameFromMainDir;
138  }
139  // remove the file from the incoming file array
140  unset($cssFiles[$key]);
141  }
142  }
143  if (!empty($filesToIncludeByType)) {
144  foreach ($filesToIncludeByType as $mediaOption => $filesToInclude) {
145  if (empty($filesToInclude)) {
146  continue;
147  }
148  $targetFile = $this->‪createMergedCssFile($filesToInclude);
149  $concatenatedOptions = [
150  'file' => $targetFile,
151  'rel' => 'stylesheet',
152  'media' => $mediaOption,
153  'compress' => true,
154  'excludeFromConcatenation' => true,
155  'forceOnTop' => false,
156  'allWrap' => ''
157  ];
158  // place the merged stylesheet on top of the stylesheets
159  $cssFiles = array_merge($cssFiles, [$targetFile => $concatenatedOptions]);
160  }
161  }
162  return $cssFiles;
163  }
164 
171  public function ‪concatenateJsFiles(array $jsFiles)
172  {
173  $concatenatedJsFileIsAsync = false;
174  $allFilesToConcatenateAreAsync = true;
175  $filesToInclude = [];
176  foreach ($jsFiles as $key => $fileOptions) {
177  // invalid section found or no concatenation allowed, so continue
178  if (empty($fileOptions['section']) || !empty($fileOptions['excludeFromConcatenation']) || !empty($fileOptions['defer'])) {
179  continue;
180  }
181  if (!isset($filesToInclude[$fileOptions['section']])) {
182  $filesToInclude[$fileOptions['section']] = [];
183  }
184  $filenameFromMainDir = $this->‪getFilenameFromMainDir($fileOptions['file']);
185  if (!empty($fileOptions['forceOnTop'])) {
186  array_unshift($filesToInclude[$fileOptions['section']], $filenameFromMainDir);
187  } else {
188  $filesToInclude[$fileOptions['section']][] = $filenameFromMainDir;
189  }
190  if (!empty($fileOptions['async']) && (bool)$fileOptions['async']) {
191  $concatenatedJsFileIsAsync = true;
192  } else {
193  $allFilesToConcatenateAreAsync = false;
194  }
195  // remove the file from the incoming file array
196  unset($jsFiles[$key]);
197  }
198  if (!empty($filesToInclude)) {
199  foreach ($filesToInclude as $section => $files) {
200  $targetFile = $this->‪createMergedJsFile($files);
201  $concatenatedOptions = [
202  'file' => $targetFile,
203  'type' => 'text/javascript',
204  'section' => $section,
205  'compress' => true,
206  'excludeFromConcatenation' => true,
207  'forceOnTop' => false,
208  'allWrap' => '',
209  'async' => $concatenatedJsFileIsAsync && $allFilesToConcatenateAreAsync,
210  ];
211  // place the merged javascript on top of the JS files
212  $jsFiles = array_merge([$targetFile => $concatenatedOptions], $jsFiles);
213  }
214  }
215  return $jsFiles;
216  }
217 
224  protected function ‪createMergedCssFile(array $filesToInclude)
225  {
226  return $this->‪createMergedFile($filesToInclude, 'css');
227  }
228 
235  protected function ‪createMergedJsFile(array $filesToInclude)
236  {
237  return $this->‪createMergedFile($filesToInclude, 'js');
238  }
239 
249  protected function ‪createMergedFile(array $filesToInclude, $type = 'css')
250  {
251  // Get file type
252  $type = strtolower(trim($type, '. '));
253  if (empty($type)) {
254  throw new \InvalidArgumentException('No valid file type given for files to be merged.', 1308957498);
255  }
256  // we add up the filenames, filemtimes and filsizes to later build a checksum over
257  // it and include it in the temporary file name
258  $unique = '';
259  foreach ($filesToInclude as $key => $filename) {
260  if (GeneralUtility::isValidUrl($filename)) {
261  // check if it is possibly a local file with fully qualified URL
262  if (GeneralUtility::isOnCurrentHost($filename) &&
263  GeneralUtility::isFirstPartOfStr(
264  $filename,
265  GeneralUtility::getIndpEnv('TYPO3_SITE_URL')
266  )
267  ) {
268  // attempt to turn it into a local file path
269  $localFilename = substr($filename, strlen(GeneralUtility::getIndpEnv('TYPO3_SITE_URL')));
270  if (@is_file(GeneralUtility::resolveBackPath($this->rootPath . $localFilename))) {
271  $filesToInclude[$key] = $localFilename;
272  } else {
273  $filesToInclude[$key] = $this->‪retrieveExternalFile($filename);
274  }
275  } else {
276  $filesToInclude[$key] = $this->‪retrieveExternalFile($filename);
277  }
278  $filename = $filesToInclude[$key];
279  }
280  $filenameAbsolute = GeneralUtility::resolveBackPath($this->rootPath . $filename);
281  if (@file_exists($filenameAbsolute)) {
282  $fileStatus = stat($filenameAbsolute);
283  $unique .= $filenameAbsolute . $fileStatus['mtime'] . $fileStatus['size'];
284  } else {
285  $unique .= $filenameAbsolute;
286  }
287  }
288  $targetFile = $this->targetDirectory . 'merged-' . md5($unique) . '.' . $type;
289  // if the file doesn't already exist, we create it
290  if (!file_exists(‪Environment::getPublicPath() . '/' . $targetFile)) {
291  $concatenated = '';
292  // concatenate all the files together
293  foreach ($filesToInclude as $filename) {
294  $filenameAbsolute = GeneralUtility::resolveBackPath($this->rootPath . $filename);
295  $filename = ‪PathUtility::stripPathSitePrefix($filenameAbsolute);
296  $contents = file_get_contents($filenameAbsolute);
297  // remove any UTF-8 byte order mark (BOM) from files
298  if (strpos($contents, "\xEF\xBB\xBF") === 0) {
299  $contents = substr($contents, 3);
300  }
301  // only fix paths if files aren't already in typo3temp (already processed)
302  if ($type === 'css' && !GeneralUtility::isFirstPartOfStr($filename, $this->targetDirectory)) {
303  $contents = $this->‪cssFixRelativeUrlPaths($contents, ‪PathUtility::dirname($filename) . '/');
304  }
305  $concatenated .= LF . $contents;
306  }
307  // move @charset, @import and @namespace statements to top of new file
308  if ($type === 'css') {
309  $concatenated = $this->‪cssFixStatements($concatenated);
310  }
311  GeneralUtility::writeFile(‪Environment::getPublicPath() . '/' . $targetFile, $concatenated);
312  }
313  return $targetFile;
314  }
315 
322  public function ‪compressCssFiles(array $cssFiles)
323  {
324  $filesAfterCompression = [];
325  foreach ($cssFiles as $key => $fileOptions) {
326  // if compression is enabled
327  if ($fileOptions['compress']) {
328  $filename = $this->‪compressCssFile($fileOptions['file']);
329  $fileOptions['compress'] = false;
330  $fileOptions['file'] = $filename;
331  $filesAfterCompression[$filename] = $fileOptions;
332  } else {
333  $filesAfterCompression[$key] = $fileOptions;
334  }
335  }
336  return $filesAfterCompression;
337  }
338 
351  public function ‪compressCssFile($filename)
352  {
353  // generate the unique name of the file
354  $filenameAbsolute = GeneralUtility::resolveBackPath($this->rootPath . $this->‪getFilenameFromMainDir($filename));
355  if (@file_exists($filenameAbsolute)) {
356  $fileStatus = stat($filenameAbsolute);
357  $unique = $filenameAbsolute . $fileStatus['mtime'] . $fileStatus['size'];
358  } else {
359  $unique = $filenameAbsolute;
360  }
361  // make sure it is again the full filename
362  $filename = ‪PathUtility::stripPathSitePrefix($filenameAbsolute);
363 
364  $pathinfo = ‪PathUtility::pathinfo($filenameAbsolute);
365  $targetFile = $this->targetDirectory . $pathinfo['filename'] . '-' . md5($unique) . '.css';
366  // only create it, if it doesn't exist, yet
367  if (!file_exists(‪Environment::getPublicPath() . '/' . $targetFile) || $this->createGzipped && !file_exists(‪Environment::getPublicPath() . '/' . $targetFile . '.gzip')) {
368  $contents = $this->‪compressCssString(file_get_contents($filenameAbsolute));
369  if (strpos($filename, $this->targetDirectory) === false) {
370  $contents = $this->‪cssFixRelativeUrlPaths($contents, ‪PathUtility::dirname($filename) . '/');
371  }
372  $this->‪writeFileAndCompressed($targetFile, $contents);
373  }
374  return $this->‪returnFileReference($targetFile);
375  }
376 
383  public function ‪compressJsFiles(array $jsFiles)
384  {
385  $filesAfterCompression = [];
386  foreach ($jsFiles as $fileName => $fileOptions) {
387  // If compression is enabled
388  if ($fileOptions['compress']) {
389  $compressedFilename = $this->‪compressJsFile($fileOptions['file']);
390  $fileOptions['compress'] = false;
391  $fileOptions['file'] = $compressedFilename;
392  $filesAfterCompression[$compressedFilename] = $fileOptions;
393  } else {
394  $filesAfterCompression[$fileName] = $fileOptions;
395  }
396  }
397  return $filesAfterCompression;
398  }
399 
406  public function ‪compressJsFile($filename)
407  {
408  // generate the unique name of the file
409  $filenameAbsolute = GeneralUtility::resolveBackPath($this->rootPath . $this->‪getFilenameFromMainDir($filename));
410  if (@file_exists($filenameAbsolute)) {
411  $fileStatus = stat($filenameAbsolute);
412  $unique = $filenameAbsolute . $fileStatus['mtime'] . $fileStatus['size'];
413  } else {
414  $unique = $filenameAbsolute;
415  }
416  $pathinfo = ‪PathUtility::pathinfo($filename);
417  $targetFile = $this->targetDirectory . $pathinfo['filename'] . '-' . md5($unique) . '.js';
418  // only create it, if it doesn't exist, yet
419  if (!file_exists(‪Environment::getPublicPath() . '/' . $targetFile) || $this->createGzipped && !file_exists(‪Environment::getPublicPath() . '/' . $targetFile . '.gzip')) {
420  $contents = file_get_contents($filenameAbsolute);
421  $this->‪writeFileAndCompressed($targetFile, $contents);
422  }
423  return $this->‪returnFileReference($targetFile);
424  }
425 
432  protected function ‪getFilenameFromMainDir($filename)
433  {
434  /*
435  * The various paths may have those values (e.g. if TYPO3 is installed in a subdir)
436  * - docRoot = /var/www/html/
437  * - Environment::getPublicPath() = /var/www/html/sites/site1/
438  * - $this->rootPath = /var/www/html/sites/site1/typo3
439  *
440  * The file names passed into this function may be either:
441  * - relative to $this->rootPath
442  * - relative to Environment::getPublicPath()
443  * - relative to docRoot
444  */
445  $docRoot = GeneralUtility::getIndpEnv('TYPO3_DOCUMENT_ROOT');
446  $fileNameWithoutSlash = ltrim($filename, '/');
447 
448  // if the file is an absolute reference within the docRoot
449  $absolutePath = $docRoot . '/' . $fileNameWithoutSlash;
450  // If the $filename stems from a call to PathUtility::getAbsoluteWebPath() it has a leading slash,
451  // hence isAbsolutePath() results in true, which is obviously wrong. Check file existence to be sure.
452  // Calling is_file without @ for a path starting with '../' causes a PHP Warning when using open_basedir restriction
453  if (‪PathUtility::isAbsolutePath($filename) && @is_file($filename)) {
454  $absolutePath = $filename;
455  }
456  if (@is_file($absolutePath)) {
457  if (strpos($absolutePath, $this->rootPath) === 0) {
458  // the path is within the current root path, simply strip rootPath off
459  return substr($absolutePath, strlen($this->rootPath));
460  }
461  // the path is not within the root path, strip off the site path, the remaining logic below
462  // takes care about adjusting the path correctly.
463  $filename = substr($absolutePath, strlen(‪Environment::getPublicPath() . '/'));
464  }
465  // if the file exists in the root path, just return the $filename
466  if (is_file($this->rootPath . $fileNameWithoutSlash)) {
467  return $fileNameWithoutSlash;
468  }
469  // if the file is from a special TYPO3 internal directory, add the missing typo3/ prefix
470  if (is_file(realpath(‪Environment::getBackendPath() . '/' . $filename))) {
471  $filename = 'typo3/' . $filename;
472  }
473  // build the file path relative to the public web path
474  if (strpos($filename, 'EXT:') === 0) {
475  $file = GeneralUtility::getFileAbsFileName($filename);
476  } elseif (strpos($filename, '../') === 0) {
477  $file = GeneralUtility::resolveBackPath(‪Environment::getBackendPath() . '/' . $filename);
478  } else {
479  $file = ‪Environment::getPublicPath() . '/' . $filename;
480  }
481 
482  // check if the file exists, and if so, return the path relative to PATH_thisScript
483  if (is_file($file)) {
484  return rtrim(‪PathUtility::getRelativePathTo($file), '/');
485  }
486  // none of above conditions were met, fallback to default behaviour
487  return $filename;
488  }
489 
497  protected function ‪checkBaseDirectory($filename, array $baseDirectories)
498  {
499  foreach ($baseDirectories as $baseDirectory) {
500  // check, if $filename starts with base directory
501  if (GeneralUtility::isFirstPartOfStr($filename, $baseDirectory)) {
502  return true;
503  }
504  }
505  return false;
506  }
507 
515  protected function ‪cssFixRelativeUrlPaths($contents, $oldDir)
516  {
517  $newDir = '../../../' . $oldDir;
518  // Replace "url()" paths
519  if (stripos($contents, 'url') !== false) {
520  $regex = '/url(\\(\\s*["\']?(?!\\/)([^"\']+)["\']?\\s*\\))/iU';
521  $contents = $this->‪findAndReplaceUrlPathsByRegex($contents, $regex, $newDir, '(\'|\')');
522  }
523  // Replace "@import" paths
524  if (stripos($contents, '@import') !== false) {
525  $regex = '/@import\\s*(["\']?(?!\\/)([^"\']+)["\']?)/i';
526  $contents = $this->‪findAndReplaceUrlPathsByRegex($contents, $regex, $newDir, '"|"');
527  }
528  return $contents;
529  }
530 
540  protected function ‪findAndReplaceUrlPathsByRegex($contents, $regex, $newDir, $wrap = '|')
541  {
542  $matches = [];
543  $replacements = [];
544  $wrap = explode('|', $wrap);
545  preg_match_all($regex, $contents, $matches);
546  foreach ($matches[2] as $matchCount => $match) {
547  // remove '," or white-spaces around
548  $match = trim($match, '\'" ');
549  // we must not rewrite paths containing ":" or "url(", e.g. data URIs (see RFC 2397)
550  if (strpos($match, ':') === false && !preg_match('/url\\s*\\(/i', $match)) {
551  $newPath = GeneralUtility::resolveBackPath($newDir . $match);
552  $replacements[$matches[1][$matchCount]] = $wrap[0] . $newPath . $wrap[1];
553  }
554  }
555  // replace URL paths in content
556  if (!empty($replacements)) {
557  $contents = str_replace(array_keys($replacements), array_values($replacements), $contents);
558  }
559  return $contents;
560  }
561 
569  protected function cssFixStatements($contents)
570  {
571  $matches = [];
572  $comment = LF . '/* moved by compressor */' . LF;
573  // nothing to do, so just return contents
574  if (stripos($contents, '@charset') === false && stripos($contents, '@import') === false && stripos($contents, '@namespace') === false) {
575  return $contents;
576  }
577  $regex = '/@(charset|import|namespace)\\s*(url)?\\s*\\(?\\s*["\']?[^"\'\\)]+["\']?\\s*\\)?\\s*;/i';
578  preg_match_all($regex, $contents, $matches);
579  if (!empty($matches[0])) {
580  // Ensure correct order of @charset, @namespace and @import
581  $charset = '';
582  $namespaces = [];
583  $imports = [];
584  foreach ($matches[1] as $index => $keyword) {
585  switch ($keyword) {
586  case 'charset':
587  if (empty($charset)) {
588  $charset = $matches[0][$index];
589  }
590  break;
591  case 'namespace':
592  $namespaces[] = $matches[0][$index];
593  break;
594  case 'import':
595  $imports[] = $matches[0][$index];
596  break;
597  }
598  }
599 
600  $namespaces = !empty($namespaces) ? implode('', $namespaces) . $comment : '';
601  $imports = !empty($imports) ? implode('', $imports) . $comment : '';
602  // remove existing statements
603  $contents = str_replace($matches[0], '', $contents);
604  // add statements to the top of contents in the order they occur in original file
605  $contents =
606  $charset
607  . $comment
608  . $namespaces
609  . $imports
610  . trim($contents);
611  }
612  return $contents;
613  }
614 
621  protected function ‪writeFileAndCompressed($filename, $contents)
622  {
623  // write uncompressed file
624  GeneralUtility::writeFile(‪Environment::getPublicPath() . '/' . $filename, $contents);
625  if ($this->createGzipped) {
626  // create compressed version
627  GeneralUtility::writeFile(‪Environment::getPublicPath() . '/' . $filename . '.gzip', gzencode($contents, $this->gzipCompressionLevel));
628  }
629  }
630 
638  protected function ‪returnFileReference($filename)
639  {
640  // if the client accepts gzip and we can create gzipped files, we give him compressed versions
641  if ($this->createGzipped && strpos(GeneralUtility::getIndpEnv('HTTP_ACCEPT_ENCODING'), 'gzip') !== false) {
642  $filename .= '.gzip';
643  }
644  return ‪PathUtility::getRelativePath($this->rootPath, ‪Environment::getPublicPath() . '/') . $filename;
645  }
646 
653  protected function ‪retrieveExternalFile($url)
654  {
655  $externalContent = GeneralUtility::getUrl($url);
656  $filename = $this->targetDirectory . 'external-' . md5($url);
657  // Write only if file does not exist OR md5 of the content is not the same as fetched one
658  if (!file_exists(‪Environment::getPublicPath() . '/' . $filename)
659  || !hash_equals(md5(file_get_contents(‪Environment::getPublicPath() . '/' . $filename)), md5($externalContent))
660  ) {
661  GeneralUtility::writeFile(‪Environment::getPublicPath() . '/' . $filename, $externalContent);
662  }
663  return $filename;
664  }
665 
672  protected function ‪compressCssString($contents)
673  {
674  // Perform some safe CSS optimizations.
675  // Regexp to match comment blocks.
676  $comment = '/\*[^*]*\*+(?:[^/*][^*]*\*+)*/';
677  // Regexp to match double quoted strings.
678  $double_quot = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
679  // Regexp to match single quoted strings.
680  $single_quot = "'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'";
681  // Strip all comment blocks, but keep double/single quoted strings.
682  $contents = preg_replace(
683  "<($double_quot|$single_quot)|$comment>Ss",
684  '$1',
685  $contents
686  );
687  // Remove certain whitespace.
688  // There are different conditions for removing leading and trailing
689  // whitespace.
690  // @see http://php.net/manual/regexp.reference.subpatterns.php
691  $contents = preg_replace(
692  '<
693  # Strip leading and trailing whitespace.
694  \s*([@{};,])\s*
695  # Strip only leading whitespace from:
696  # - Closing parenthesis: Retain "@media (bar) and foo".
697  | \s+([\‍)])
698  # Strip only trailing whitespace from:
699  # - Opening parenthesis: Retain "@media (bar) and foo".
700  # - Colon: Retain :pseudo-selectors.
701  | ([\‍(:])\s+
702  >xS',
703  // Only one of the three capturing groups will match, so its reference
704  // will contain the wanted value and the references for the
705  // two non-matching groups will be replaced with empty strings.
706  '$1$2$3',
707  $contents
708  );
709  // End the file with a new line.
710  $contents = trim($contents);
711  // Ensure file ends in newline.
712  $contents .= LF;
713  return $contents;
714  }
715 }
‪TYPO3\CMS\Core\Resource\ResourceCompressor\getFilenameFromMainDir
‪string getFilenameFromMainDir($filename)
Definition: ResourceCompressor.php:427
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Core\Resource\ResourceCompressor\$targetDirectory
‪string $targetDirectory
Definition: ResourceCompressor.php:30
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:185
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:371
‪TYPO3\CMS\Core\Resource\ResourceCompressor\$rootPath
‪string $rootPath
Definition: ResourceCompressor.php:34
‪TYPO3\CMS\Core\Utility\PathUtility\getRelativePath
‪static string null getRelativePath($sourcePath, $targetPath)
Definition: PathUtility.php:72
‪TYPO3\CMS\Core\Resource\ResourceCompressor
Definition: ResourceCompressor.php:27
‪TYPO3\CMS\Core\Resource\ResourceCompressor\retrieveExternalFile
‪string retrieveExternalFile($url)
Definition: ResourceCompressor.php:648
‪TYPO3\CMS\Core\Resource\ResourceCompressor\$htaccessTemplate
‪string $htaccessTemplate
Definition: ResourceCompressor.php:48
‪TYPO3\CMS\Core\Resource\ResourceCompressor\createMergedJsFile
‪mixed createMergedJsFile(array $filesToInclude)
Definition: ResourceCompressor.php:230
‪TYPO3\CMS\Core\Resource\ResourceCompressor\createMergedCssFile
‪mixed createMergedCssFile(array $filesToInclude)
Definition: ResourceCompressor.php:219
‪TYPO3\CMS\Core\Resource\ResourceCompressor\$createGzipped
‪bool $createGzipped
Definition: ResourceCompressor.php:40
‪TYPO3\CMS\Core\Utility\PathUtility\pathinfo
‪static string array pathinfo($path, $options=null)
Definition: PathUtility.php:207
‪TYPO3\CMS\Core\Resource\ResourceCompressor\cssFixStatements
‪string cssFixStatements($contents)
Definition: ResourceCompressor.php:564
‪TYPO3\CMS\Core\Utility\PathUtility\getRelativePathTo
‪static string null getRelativePathTo($targetPath)
Definition: PathUtility.php:31
‪TYPO3\CMS\Core\Resource\ResourceCompressor\compressCssFiles
‪array compressCssFiles(array $cssFiles)
Definition: ResourceCompressor.php:317
‪TYPO3\CMS\Core\Resource\ResourceCompressor\setRootPath
‪setRootPath($rootPath)
Definition: ResourceCompressor.php:91
‪TYPO3\CMS\Core\Resource\ResourceCompressor\returnFileReference
‪string returnFileReference($filename)
Definition: ResourceCompressor.php:633
‪TYPO3\CMS\Core\Resource\ResourceCompressor\compressJsFile
‪string compressJsFile($filename)
Definition: ResourceCompressor.php:401
‪TYPO3\CMS\Core\Resource\ResourceCompressor\__construct
‪__construct()
Definition: ResourceCompressor.php:59
‪TYPO3\CMS\Core\Core\Environment\getBackendPath
‪static string getBackendPath()
Definition: Environment.php:223
‪TYPO3\CMS\Core\Utility\PathUtility\isAbsolutePath
‪static bool isAbsolutePath($path)
Definition: PathUtility.php:222
‪TYPO3\CMS\Core\Resource\ResourceCompressor\writeFileAndCompressed
‪writeFileAndCompressed($filename, $contents)
Definition: ResourceCompressor.php:616
‪TYPO3\CMS\Core\Resource
Definition: generateMimeTypes.php:37
‪TYPO3\CMS\Core\Resource\ResourceCompressor\findAndReplaceUrlPathsByRegex
‪string findAndReplaceUrlPathsByRegex($contents, $regex, $newDir, $wrap='|')
Definition: ResourceCompressor.php:535
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Core\Resource\ResourceCompressor\concatenateCssFiles
‪array concatenateCssFiles(array $cssFiles, array $options=[])
Definition: ResourceCompressor.php:108
‪TYPO3\CMS\Core\Resource\ResourceCompressor\compressCssFile
‪string compressCssFile($filename)
Definition: ResourceCompressor.php:346
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Core\Resource\ResourceCompressor\compressCssString
‪string compressCssString($contents)
Definition: ResourceCompressor.php:667
‪TYPO3\CMS\Core\Resource\ResourceCompressor\createMergedFile
‪mixed createMergedFile(array $filesToInclude, $type='css')
Definition: ResourceCompressor.php:244
‪TYPO3\CMS\Core\Resource\ResourceCompressor\cssFixRelativeUrlPaths
‪string cssFixRelativeUrlPaths($contents, $oldDir)
Definition: ResourceCompressor.php:510
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Resource\ResourceCompressor\compressJsFiles
‪array compressJsFiles(array $jsFiles)
Definition: ResourceCompressor.php:378
‪TYPO3\CMS\Core\Resource\ResourceCompressor\checkBaseDirectory
‪bool checkBaseDirectory($filename, array $baseDirectories)
Definition: ResourceCompressor.php:492
‪TYPO3\CMS\Core\Resource\ResourceCompressor\$gzipCompressionLevel
‪int $gzipCompressionLevel
Definition: ResourceCompressor.php:44
‪TYPO3\CMS\Core\Resource\ResourceCompressor\concatenateJsFiles
‪array concatenateJsFiles(array $jsFiles)
Definition: ResourceCompressor.php:166