1<?php 2 3/** 4 * 2007-2016 PrestaShop. 5 * 6 * NOTICE OF LICENSE 7 * 8 * This source file is subject to the Open Software License (OSL 3.0) 9 * that is bundled with this package in the file LICENSE.txt. 10 * It is also available through the world-wide-web at this URL: 11 * http://opensource.org/licenses/osl-3.0.php 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@prestashop.com so we can send you a copy immediately. 15 * 16 * DISCLAIMER 17 * 18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 19 * versions in the future. If you wish to customize PrestaShop for your 20 * needs please refer to http://www.prestashop.com for more information. 21 * 22 * @author PrestaShop SA <contact@prestashop.com> 23 * @copyright 2007-2015 PrestaShop SA 24 * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 25 * International Registered Trademark & Property of PrestaShop SA 26 */ 27 28namespace PrestaShop\TranslationToolsBundle\Translation\Extractor; 29 30use Twig_Source; 31use Twig_Environment; 32use Twig_Error; 33use PrestaShop\TranslationToolsBundle\Twig\Lexer; 34use Symfony\Bridge\Twig\Translation\TwigExtractor as BaseTwigExtractor; 35use Symfony\Component\Finder\SplFileInfo; 36use Symfony\Component\Translation\MessageCatalogue; 37use Symfony\Component\Translation\Extractor\ExtractorInterface; 38use Symfony\Bridge\Twig\Extension\TranslationExtension; 39 40class TwigExtractor extends BaseTwigExtractor implements ExtractorInterface 41{ 42 use TraitExtractor; 43 44 /** 45 * Prefix for found message. 46 * 47 * @var string 48 */ 49 private $prefix = ''; 50 51 /** 52 * The twig environment. 53 * 54 * @var Twig_Environment 55 */ 56 private $twig; 57 58 /** 59 * @var Lexer 60 */ 61 private $twigLexer; 62 63 /** 64 * The twig environment. 65 * 66 * @var Twig_Environment 67 */ 68 public function __construct(Twig_Environment $twig) 69 { 70 $this->twig = $twig; 71 $this->twigLexer = new Lexer($this->twig); 72 } 73 74 /** 75 * {@inheritdoc} 76 */ 77 public function extract($resource, MessageCatalogue $catalogue) 78 { 79 $files = $this->extractFiles($resource); 80 foreach ($files as $file) { 81 if (!$this->canBeExtracted($file->getRealpath())) { 82 continue; 83 } 84 85 try { 86 $this->extractTemplateFile($file, $catalogue); 87 } catch (Twig_Error $e) { 88 if ($file instanceof SplFileInfo) { 89 $e->setSourceContext(new Twig_Source( 90 $e->getSourceContext()->getCode(), 91 $e->getSourceContext()->getName(), 92 $file->getRelativePathname() 93 )); 94 } elseif ($file instanceof \SplFileInfo) { 95 $e->setSourceContext(new Twig_Source( 96 $e->getSourceContext()->getCode(), 97 $e->getSourceContext()->getName(), 98 $file->getRealPath() 99 )); 100 } 101 102 throw $e; 103 } 104 } 105 } 106 107 /** 108 * {@inheritdoc} 109 */ 110 protected function extractTemplateFile($file, MessageCatalogue $catalogue) 111 { 112 if (!$file instanceof \SplFileInfo) { 113 $file = new \SplFileInfo($file); 114 } 115 116 $visitor = $this->twig->getExtension(TranslationExtension::class)->getTranslationNodeVisitor(); 117 $visitor->enable(); 118 119 $this->twig->setLexer(new Lexer($this->twig)); 120 121 $tokens = $this->twig->tokenize(new Twig_Source(file_get_contents($file->getPathname()), $file->getFilename())); 122 $this->twig->parse($tokens); 123 124 $comments = $this->twigLexer->getComments(); 125 126 foreach ($visitor->getMessages() as $message) { 127 $domain = $this->resolveDomain(isset($message[1]) ? $message[1] : null); 128 129 $catalogue->set( 130 $message[0], 131 $this->prefix.trim($message[0]), 132 $domain 133 ); 134 135 $metadata = [ 136 'file' => $file->getRealpath(), 137 'line' => $message['line'], 138 ]; 139 140 $comment = $this->getEntryComment($comments, $file->getFilename(), ($message['line'] - 1)); 141 142 if (null != $comment) { 143 $metadata['comment'] = $comment; 144 } 145 146 if (isset($message['line'])) { 147 $metadata['comment'] = $this->getEntryComment($comments, $file->getFilename(), ($message['line'] - 1)); 148 } 149 150 $catalogue->setMetadata($message[0], $metadata, $domain); 151 } 152 153 $visitor->disable(); 154 } 155 156 /** 157 * @param $comments 158 * @param $file 159 * @param $line 160 * 161 * @return array 162 */ 163 public function getEntryComment($comments, $file, $line) 164 { 165 foreach ($comments as $comment) { 166 if ($comment['file'] == $file && $comment['line'] == $line) { 167 return $comment['comment']; 168 } 169 } 170 } 171 172 /** 173 * @param string $directory 174 * 175 * @return Finder 176 */ 177 protected function extractFromDirectory($directory) 178 { 179 return $this->getFinder()->files()->name('*.twig')->in($directory); 180 } 181} 182