public function testLessFileCompilation() { $thisString = $this->toString(); $this->assertTrue(is_string($this->file) && is_file($this->file) && is_readable($this->file), "{$thisString} must refer to a readable file"); $compiler = ResourceLoader::getLessCompiler(RequestContext::getMain()->getConfig()); $this->assertNotNull($compiler->compileFile($this->file)); }
public function execute() { $result = false; $resourceLoader = new ResourceLoader(); foreach ($resourceLoader->getModuleNames() as $name) { /** @var ResourceLoaderFileModule $module */ $module = $resourceLoader->getModule($name); if (!$module || !$module instanceof ResourceLoaderFileModule) { continue; } $hadErrors = false; foreach ($module->getAllStyleFiles() as $file) { if ($module->getStyleSheetLang($file) !== 'less') { continue; } try { $compiler = ResourceLoader::getLessCompiler(); $compiler->compileFile($file); } catch (Exception $e) { if (!$hadErrors) { $this->error("Errors checking module {$name}:\n"); $hadErrors = true; } $this->error($e->getMessage() . "\n"); $result = true; } } } if (!$result) { $this->output("No errors found\n"); } else { die(1); } }
/** * @dataProvider lessProvider */ public function testLessFile($lessFile) { $cssFile = substr($lessFile, 0, -4) . 'css'; if (!file_exists($cssFile)) { $this->fail("No css file found to assert equal to {$lessFile}"); return; } $expect = file_get_contents($cssFile); $content = file_get_contents($lessFile); $result = ResourceLoader::getLessCompiler(RequestContext::getMain()->getConfig())->compile($content, $lessFile); $this->assertEquals($expect, $result); }
/** * Get a LESS compiler instance for this module in given context. * * Just calls ResourceLoader::getLessCompiler() by default to get a global compiler. * * @param ResourceLoaderContext $context * @throws MWException * @since 1.24 * @return Less_Parser */ protected function getLessCompiler(ResourceLoaderContext $context = null) { return ResourceLoader::getLessCompiler($this->getConfig()); }
/** * 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::newAccelerator(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 = ResourceLoader::getLessCompiler($this->getConfig(), $vars); $css = $compiler->parseFile($fileName)->getCss(); $files = $compiler->AllParsedFiles(); $this->localFileRefs = array_merge($this->localFileRefs, $files); $cache->set($cacheKey, array('css' => $css, 'files' => $files, 'hash' => FileContentsHasher::getFileContentsHash($files)), 60 * 60 * 24); // 86400 seconds, or 24 hours. return $css; }
/** * Compile a LESS file into CSS. * * If invalid, returns replacement CSS source consisting of the compilation * error message encoded as a comment. To save work, we cache a result object * which comprises the compiled CSS and the names & mtimes of the files * that were processed. lessphp compares the cached & current mtimes and * recompiles as necessary. * * @since 1.22 * @throws Exception If Less encounters a parse error * @throws MWException If Less compilation returns unexpection result * @param string $fileName File path of LESS source * @return string: CSS source */ protected function compileLESSFile($fileName) { $key = self::getLESSCacheKey($fileName); $cache = wfGetCache(CACHE_ANYTHING); // The input to lessc. Either an associative array representing the // cached results of a previous compilation, or the string file name if // no cache result exists. $source = $cache->get($key); if (!is_array($source) || !isset($source['root'])) { $source = $fileName; } $compiler = ResourceLoader::getLessCompiler(); $result = null; $result = $compiler->cachedCompile($source); if (!is_array($result)) { throw new MWException('LESS compiler result has type ' . gettype($result) . '; array expected.'); } $this->localFileRefs += array_keys($result['files']); $cache->set($key, $result); return $result['compiled']; }
/** * Get the raw vector CSS, flipping if needed * * @todo Possibly get rid of this function and use ResourceLoader in the manner it was * designed to be used in, rather than just grabbing a list of filenames from it, * and not properly handling such details as media types in module definitions. * * @param string $dir 'ltr' or 'rtl' * @return String */ public function getCSS($dir) { // All CSS files these modules reference will be concatenated in sequence // and loaded as one file. $moduleNames = array('mediawiki.legacy.shared', 'skins.common.interface', 'skins.vector.styles', 'mediawiki.legacy.config'); $prepend = ''; $css = ''; $resourceLoader = new ResourceLoader(); foreach ($moduleNames as $moduleName) { /** @var ResourceLoaderFileModule $module */ $module = $resourceLoader->getModule($moduleName); $cssFileNames = $module->getAllStyleFiles(); wfSuppressWarnings(); foreach ($cssFileNames as $cssFileName) { if (!file_exists($cssFileName)) { $prepend .= ResourceLoader::makeComment("Unable to find {$cssFileName}."); continue; } if (!is_readable($cssFileName)) { $prepend .= ResourceLoader::makeComment("Unable to read {$cssFileName}. " . "Please check file permissions."); continue; } try { if (preg_match('/\\.less$/', $cssFileName)) { // Run the LESS compiler for *.less files (bug 55589) $compiler = ResourceLoader::getLessCompiler(); $cssFileContents = $compiler->compileFile($cssFileName); } else { // Regular CSS file $cssFileContents = file_get_contents($cssFileName); } if ($cssFileContents) { // Rewrite URLs, though don't bother embedding images. While static image // files may be cached, CSS returned by this function is definitely not. $cssDirName = dirname($cssFileName); $css .= CSSMin::remap($cssFileContents, $cssDirName, '..' . str_replace(array($GLOBALS['IP'], DIRECTORY_SEPARATOR), array('', '/'), $cssDirName), false); } else { $prepend .= ResourceLoader::makeComment("Unable to read {$cssFileName}."); } } catch (Exception $e) { $prepend .= ResourceLoader::formatException($e); } $css .= "\n"; } wfRestoreWarnings(); } $css = $prepend . $css; if ($dir == 'rtl') { $css = CSSJanus::transform($css, true); } return $css; }
/** * Compile a LESS file into CSS. * * Keeps track of all used files and adds them to localFileRefs. * * @since 1.22 * @throws Exception If lessc encounters a parse error * @param string $fileName File path of LESS source * @return string CSS source */ protected function compileLessFile($fileName) { $compiler = ResourceLoader::getLessCompiler($this->getConfig()); $result = $compiler->compileFile($fileName); $this->localFileRefs += array_keys($compiler->allParsedFiles()); return $result; }