/**
  * Get the singleton instance of this class.
  *
  * @return FileContentsHasher
  */
 public static function singleton()
 {
     if (!self::$instance) {
         self::$instance = new self();
     }
     return self::$instance;
 }
 /**
  * @covers FileContentsHasher::getFileContentsHash
  * @covers FileContentsHasher::getFileContentsHashInternal
  * @dataProvider provideMultipleFiles
  */
 public function testMultipleFileHash($files)
 {
     $fileNames = [];
     $hashes = [];
     foreach ($files as $fileInfo) {
         list($fileName, $contents) = $fileInfo;
         $fileNames[] = $fileName;
         $hashes[] = md5($contents);
     }
     $expectedHash = md5(implode('', $hashes));
     $actualHash = FileContentsHasher::getFileContentsHash($fileNames, 'md5');
     $this->assertEquals($expectedHash, $actualHash);
     $actualHashRepeat = FileContentsHasher::getFileContentsHash($fileNames, 'md5');
     $this->assertEquals($expectedHash, $actualHashRepeat);
 }
 /**
  * Compile a LESS file into CSS.
  *
  * Keeps track of all used files and adds them to localFileRefs.
  *
  * @since 1.22
  * @since 1.27 Added $context paramter.
  * @throws Exception If less.php encounters a parse error
  * @param string $fileName File path of LESS source
  * @param ResourceLoaderContext $context Context in which to generate script
  * @return string CSS source
  */
 protected function compileLessFile($fileName, ResourceLoaderContext $context)
 {
     static $cache;
     if (!$cache) {
         $cache = ObjectCache::getLocalServerInstance(CACHE_ANYTHING);
     }
     // Construct a cache key from the LESS file name and a hash digest
     // of the LESS variables used for compilation.
     $vars = $this->getLessVars($context);
     ksort($vars);
     $varsHash = hash('md4', serialize($vars));
     $cacheKey = $cache->makeGlobalKey('LESS', $fileName, $varsHash);
     $cachedCompile = $cache->get($cacheKey);
     // If we got a cached value, we have to validate it by getting a
     // checksum of all the files that were loaded by the parser and
     // ensuring it matches the cached entry's.
     if (isset($cachedCompile['hash'])) {
         $contentHash = FileContentsHasher::getFileContentsHash($cachedCompile['files']);
         if ($contentHash === $cachedCompile['hash']) {
             $this->localFileRefs = array_merge($this->localFileRefs, $cachedCompile['files']);
             return $cachedCompile['css'];
         }
     }
     $compiler = $context->getResourceLoader()->getLessCompiler($vars);
     $css = $compiler->parseFile($fileName)->getCss();
     $files = $compiler->AllParsedFiles();
     $this->localFileRefs = array_merge($this->localFileRefs, $files);
     $cache->set($cacheKey, ['css' => $css, 'files' => $files, 'hash' => FileContentsHasher::getFileContentsHash($files)], 60 * 60 * 24);
     // 86400 seconds, or 24 hours.
     return $css;
 }
 /**
  * Compute a non-cryptographic string hash of a file's contents.
  * If the file does not exist or cannot be read, returns an empty string.
  *
  * @since 1.26 Uses MD4 instead of SHA1.
  * @param string $filePath File path
  * @return string Hash
  */
 protected static function safeFileHash($filePath)
 {
     return FileContentsHasher::getFileContentsHash($filePath);
 }