This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Agavi\Renderer; |
||
3 | |||
4 | // +---------------------------------------------------------------------------+ |
||
5 | // | This file is part of the Agavi package. | |
||
6 | // | Copyright (c) 2005-2011 the Agavi Project. | |
||
7 | // | | |
||
8 | // | For the full copyright and license information, please view the LICENSE | |
||
9 | // | file that was distributed with this source code. You can also view the | |
||
10 | // | LICENSE file online at http://www.agavi.org/LICENSE.txt | |
||
11 | // | vi: set noexpandtab: | |
||
12 | // | Local Variables: | |
||
13 | // | indent-tabs-mode: t | |
||
14 | // | End: | |
||
15 | // +---------------------------------------------------------------------------+ |
||
16 | use Agavi\Exception\RenderException; |
||
17 | use Agavi\Util\ArrayPathDefinition; |
||
18 | use Agavi\View\TemplateLayer; |
||
19 | |||
20 | /** |
||
21 | * XsltRenderer uses an XML Stylesheet Language Template to render the |
||
22 | * given input (an XML document in $inner). |
||
23 | * |
||
24 | * @package agavi |
||
25 | * @subpackage renderer |
||
26 | * |
||
27 | * @author David Zülke <[email protected]> |
||
28 | * @copyright Authors |
||
29 | * @copyright The Agavi Project |
||
30 | * |
||
31 | * @since 1.0.4 |
||
32 | * |
||
33 | * @version $Id$ |
||
34 | */ |
||
35 | class XsltRenderer extends Renderer implements ReusableRendererInterface |
||
36 | { |
||
37 | const ENVELOPE_XMLNS = 'http://agavi.org/agavi/renderer/xslt/envelope/1.0'; |
||
38 | |||
39 | /** |
||
40 | * @var string A string with the default template file extension, |
||
41 | * including the dot. |
||
42 | */ |
||
43 | protected $defaultExtension = '.xsl'; |
||
44 | |||
45 | /** |
||
46 | * Load an XML document from a string, return a DOMDocument and return errors |
||
47 | * in case something went wrong. |
||
48 | * |
||
49 | * @param string $source The XML source to load. |
||
50 | * @param int $options libxml option flags for loading. |
||
51 | * |
||
52 | * @return \DOMDocument The parsed XML document. |
||
53 | * |
||
54 | * @author David Zülke <[email protected]> |
||
55 | * @since 1.0.4 |
||
56 | */ |
||
57 | View Code Duplication | protected function loadDomDocumentXml($source, $options = 0) |
|
0 ignored issues
–
show
|
|||
58 | { |
||
59 | $luie = libxml_use_internal_errors(true); |
||
60 | libxml_clear_errors(); |
||
61 | |||
62 | $result = new \DOMDocument(); |
||
63 | $loaded = @$result->loadXML($source, $options); |
||
64 | |||
65 | if (libxml_get_last_error() !== false || !$loaded) { |
||
66 | $errors = array(); |
||
67 | foreach (libxml_get_errors() as $error) { |
||
68 | $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message); |
||
69 | } |
||
70 | libxml_clear_errors(); |
||
71 | libxml_use_internal_errors($luie); |
||
72 | |||
73 | if (!$errors) { |
||
0 ignored issues
–
show
The expression
$errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
74 | $errors = array('Unknown error (document empty?)'); |
||
75 | } |
||
76 | throw new \DOMException( |
||
77 | sprintf( |
||
78 | 'Error%s occurred while parsing the document: ' . "\n\n%s", |
||
79 | count($errors) > 1 ? 's' : '', |
||
80 | implode("\n", $errors) |
||
81 | ) |
||
82 | ); |
||
83 | } |
||
84 | |||
85 | libxml_use_internal_errors($luie); |
||
86 | |||
87 | return $result; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * Load an XML document from a file, return a DOMDocument and return errors in |
||
92 | * case something went wrong. |
||
93 | * |
||
94 | * @param string $source The XML source to load. |
||
95 | * @param int $options libxml option flags for loading. |
||
96 | * |
||
97 | * @return \DOMDocument The parsed XML document. |
||
98 | * |
||
99 | * @author David Zülke <[email protected]> |
||
100 | * @since 1.0.4 |
||
101 | */ |
||
102 | View Code Duplication | protected function loadDomDocument($source, $options = 0) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
103 | { |
||
104 | $luie = libxml_use_internal_errors(true); |
||
105 | libxml_clear_errors(); |
||
106 | |||
107 | $result = new \DOMDocument(); |
||
108 | $result->load($source, $options); |
||
109 | |||
110 | if (libxml_get_last_error() !== false) { |
||
111 | $errors = array(); |
||
112 | foreach (libxml_get_errors() as $error) { |
||
113 | $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message); |
||
114 | } |
||
115 | libxml_clear_errors(); |
||
116 | libxml_use_internal_errors($luie); |
||
117 | |||
118 | if (!$errors) { |
||
0 ignored issues
–
show
The expression
$errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
119 | $errors = array('Unknown error (document empty?)'); |
||
120 | } |
||
121 | throw new \DOMException( |
||
122 | sprintf( |
||
123 | 'Error%s occurred while parsing the document: ' . "\n\n%s", |
||
124 | count($errors) > 1 ? 's' : '', |
||
125 | implode("\n", $errors) |
||
126 | ) |
||
127 | ); |
||
128 | } |
||
129 | |||
130 | libxml_use_internal_errors($luie); |
||
131 | |||
132 | return $result; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Render the presentation and return the result. |
||
137 | * |
||
138 | * @param TemplateLayer $layer The template layer to render. |
||
139 | * @param array $attributes The template variables. |
||
140 | * @param array $slots The slots. |
||
141 | * @param array $moreAssigns Associative array of additional assigns. |
||
142 | * |
||
143 | * @return string A rendered result. |
||
144 | * |
||
145 | * @author David Zülke <[email protected]> |
||
146 | * @since 1.1.0 |
||
147 | */ |
||
148 | public function render(TemplateLayer $layer, array &$attributes = array(), array &$slots = array(), array &$moreAssigns = array()) |
||
149 | { |
||
150 | if ($this->getParameter('envelope', true)) { |
||
151 | if (!($moreAssigns['inner'] instanceof \DOMDocument)) { |
||
152 | // plain text, load it as a document |
||
153 | try { |
||
154 | $inner = $this->loadDomDocumentXml($moreAssigns['inner']); |
||
155 | } catch (\DOMException $e) { |
||
156 | throw new RenderException(sprintf("Unable to load input document for layer '%s'.\n\n%s", $layer->getName(), $e->getMessage()), 0, $e); |
||
0 ignored issues
–
show
The method
getName does not exist on object<Agavi\View\TemplateLayer> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
157 | } |
||
158 | } else { |
||
159 | $inner = $moreAssigns['inner']; |
||
160 | } |
||
161 | |||
162 | // construct envelope |
||
163 | $doc = new \DOMDocument(); |
||
164 | $doc->appendChild($doc->createElementNS(self::ENVELOPE_XMLNS, 'envelope')); |
||
165 | |||
166 | // inner content container |
||
167 | $doc->documentElement->appendChild($innerWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'inner')); |
||
168 | $innerWrapper->appendChild($doc->importNode($inner->documentElement, true)); |
||
169 | |||
170 | // slots container |
||
171 | $slotsWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'slots'); |
||
172 | $doc->documentElement->appendChild($slotsWrapper); |
||
173 | |||
174 | // flatten slots, iterate and wrap them each |
||
175 | $flattenedSlots = ArrayPathDefinition::flatten($slots); |
||
176 | foreach ($flattenedSlots as $slotName => $slotContent) { |
||
177 | if (!($slotContent instanceof \DOMDocument)) { |
||
178 | try { |
||
179 | $slot = $this->loadDomDocumentXml($slotContent); |
||
180 | } catch (\Exception $e) { |
||
181 | throw new RenderException(sprintf("Unable to load contents for slot '%s'.\n\n%s", $slotName, $e->getMessage()), 0, $e); |
||
182 | } |
||
183 | } else { |
||
184 | $slot = $slotContent; |
||
185 | } |
||
186 | |||
187 | $slotWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'slot'); |
||
188 | $slotWrapper->setAttribute('name', $slotName); |
||
189 | $slotWrapper->appendChild($doc->importNode($slot->documentElement, true)); |
||
190 | |||
191 | $slotsWrapper->appendChild($slotWrapper); |
||
192 | } |
||
193 | } else { |
||
194 | if (!($moreAssigns['inner'] instanceof \DOMDocument)) { |
||
195 | // plain text, load it as a document |
||
196 | $doc = $this->loadDomDocumentXml($moreAssigns['inner']); |
||
197 | } else { |
||
198 | $doc = $moreAssigns['inner']; |
||
199 | } |
||
200 | // This will pretty much never work, so we're not doing it. Users must enable the envelope feature to use slots. |
||
201 | // Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: Cannot create XPath expression (string contains both quote and double-quotes) |
||
202 | // $flattenedSlots = AgaviArrayPathDefinition::flatten($slots); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
50% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
203 | // foreach($flattenedSlots as $slotName => $slotContent) { |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
60% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
204 | // if($slotContent instanceof DOMDocument) { |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
55% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
205 | // $slotContent = $slotContent->saveXML(); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
55% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
206 | // } |
||
207 | // $xsl->setParameter('', 'slot:' . $slotName, addslashes($slotContent)); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
62% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
208 | // } |
||
209 | } |
||
210 | |||
211 | try { |
||
212 | $xslt = $this->loadDomDocument($layer->getResourceStreamIdentifier()); |
||
213 | } catch (\DOMException $e) { |
||
214 | throw new RenderException(sprintf("Unable to load template '%s'.\n\n%s", $layer->getResourceStreamIdentifier(), $e->getMessage()), 0, $e); |
||
215 | } |
||
216 | |||
217 | $xsl = new \XSLTProcessor(); |
||
218 | $xsl->importStylesheet($xslt); |
||
219 | foreach ($attributes as $name => $attribute) { |
||
220 | if (is_scalar($attribute) || (is_object($attribute) && method_exists($attribute, '__toString'))) { |
||
221 | $xsl->setParameter('', $name, $attribute); |
||
222 | } |
||
223 | } |
||
224 | |||
225 | return $xsl->transformToXML($doc); |
||
226 | } |
||
227 | } |
||
228 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.