| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | namespace Webrouse\AssetMacro; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | use Latte; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use Latte\Macros\MacroSet; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use Nette\Caching\Cache; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use Nette\Caching\IStorage; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use Nette\Utils\Strings; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use Nette\Utils\Validators; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 | 1 |  | class AssetMacro extends MacroSet | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | 	// Name of the Latte provider for manifest service | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | 	public const MANIFEST_PROVIDER = 'assetMacroManifestService'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 | 1 |  | 	public static function install(Latte\Compiler $compiler): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 | 1 |  | 		$me = new self($compiler); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 | 1 |  | 		$me->addMacro('asset', [$me, 'macroAsset']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 | 1 |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 | 1 |  | 	public function macroAsset(Latte\MacroNode $node, Latte\PhpWriter $writer): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 | 1 |  | 		if ($node->modifiers && $node->modifiers !== '|noescape') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 | 1 |  | 			throw new Latte\CompileException('Only \'noescape\' modifier is allowed in ' . $node->getNotation()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | 		// Validate arguments count | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 | 1 |  | 		$args = trim($node->args); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 | 1 |  | 		$argsCount = $args === '' ? 0 : (substr_count($args, ',') + 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 | 1 |  | 		if ($argsCount === 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 1 |  | 			throw new Latte\CompileException('Asset macro requires at least one argument.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 | 1 |  | 		} elseif ($argsCount > 4) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 1 |  | 			throw new Latte\CompileException('Asset macro must have no more than 4 arguments.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 | 1 |  | 		return $writer->write( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 1 |  | 			'echo ' . ($node->modifiers !== '|noescape' ? '%escape' : '') . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 | 1 |  | 			'(' . self::class . '::getOutput(' . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 | 1 |  | 			'%node.word, ' . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 | 1 |  | 			'%node.array, ' . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 | 1 |  | 			'$this->global->' . self::MANIFEST_PROVIDER . ', ' . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 | 1 |  | 			'$this->global->cacheStorage ?? null))'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 | 1 |  | 	public static function getOutput(string $asset, array $args, ManifestService $manifestService, IStorage $storage = null): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 | 1 |  | 		$config = $manifestService->getConfig(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  | 		// Cache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 | 1 |  | 		$cacheKey = md5(implode(';', [$asset, serialize($args), $config->getHash()])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 | 1 |  | 		$cache = ($config->isCacheEnabled() && $storage) ? new Cache($storage, 'Webrouse.AssetMacro') : null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  | 		// Load cached value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 | 1 |  | 		if ($cache && ($output = $cache->load($cacheKey)) !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 1 |  | 			return (string) $output; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  | 		// Generate output and store value to cache | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 | 1 |  | 		$output = self::generateOutput($asset, $args, $config, $manifestService); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 1 |  | 		if ($cache) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 1 |  | 			$cache->save($cacheKey, $output); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 1 |  | 		return $output; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 1 |  | 	public static function generateOutput(string $asset, array $args, Config $config, ManifestService $manifestService): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 | 1 |  | 		[$format, $needed, $absolute] = self::processArguments($asset, $args, $config); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                            
                                                                                            
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 1 |  | 		$asset = $manifestService->getAsset($asset, $needed); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 1 |  | 		return $asset ? $manifestService->formatOutput($asset, $format, $absolute) : ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 1 |  | 	private static function processArguments(string $asset, array $args, Config $config): array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 | 1 |  | 		$format = $args['format'] ?? ($args[0] ?? $config->getDefaultFormat()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 1 |  | 		$needed = $args['need'] ?? ($args[1] ?? true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 1 |  | 		$absolute = $args['absolute'] ?? ($args[2] ?? false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 | 1 |  | 		Validators::assert($asset, 'string', 'path'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 1 |  | 		Validators::assert($format, 'string', 'format'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 1 |  | 		Validators::assert($needed, 'bool', 'need'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 1 |  | 		Validators::assert($needed, 'bool', 'absolute'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 1 |  | 		if (Strings::startsWith($asset, '//')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 1 |  | 			$absolute = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 1 |  | 		return [$format, $needed, $absolute]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  | } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |  | 
            
                        
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.