Popup by Supsystic - Version 1.9.5

Version Description

/ 22.06.2017 * Fix issue with saving SMTP and other Third Party emails providers data * Minor improvements

Download this release

Release Info

Developer supsystic.com
Plugin Icon 128x128 Popup by Supsystic
Version 1.9.5
Comparing to
See all releases

Version 1.9.5

Files changed (178) hide show
  1. classes/Twig/Autoloader.php +48 -0
  2. classes/Twig/Compiler.php +270 -0
  3. classes/Twig/CompilerInterface.php +36 -0
  4. classes/Twig/Environment.php +1254 -0
  5. classes/Twig/Error.php +248 -0
  6. classes/Twig/Error/Loader.php +31 -0
  7. classes/Twig/Error/Runtime.php +20 -0
  8. classes/Twig/Error/Syntax.php +20 -0
  9. classes/Twig/ExistsLoaderInterface.php +29 -0
  10. classes/Twig/ExpressionParser.php +598 -0
  11. classes/Twig/Extension.php +93 -0
  12. classes/Twig/Extension/Core.php +1462 -0
  13. classes/Twig/Extension/Debug.php +71 -0
  14. classes/Twig/Extension/Escaper.php +107 -0
  15. classes/Twig/Extension/Optimizer.php +35 -0
  16. classes/Twig/Extension/Sandbox.php +112 -0
  17. classes/Twig/Extension/Staging.php +113 -0
  18. classes/Twig/Extension/StringLoader.php +64 -0
  19. classes/Twig/ExtensionInterface.php +83 -0
  20. classes/Twig/Filter.php +81 -0
  21. classes/Twig/Filter/Function.php +37 -0
  22. classes/Twig/Filter/Method.php +39 -0
  23. classes/Twig/Filter/Node.php +39 -0
  24. classes/Twig/FilterCallableInterface.php +23 -0
  25. classes/Twig/FilterInterface.php +42 -0
  26. classes/Twig/Function.php +71 -0
  27. classes/Twig/Function/Function.php +38 -0
  28. classes/Twig/Function/Method.php +40 -0
  29. classes/Twig/Function/Node.php +39 -0
  30. classes/Twig/FunctionCallableInterface.php +23 -0
  31. classes/Twig/FunctionInterface.php +39 -0
  32. classes/Twig/Lexer.php +409 -0
  33. classes/Twig/LexerInterface.php +32 -0
  34. classes/Twig/Loader/Array.php +95 -0
  35. classes/Twig/Loader/Chain.php +138 -0
  36. classes/Twig/Loader/Filesystem.php +236 -0
  37. classes/Twig/Loader/String.php +59 -0
  38. classes/Twig/LoaderInterface.php +52 -0
  39. classes/Twig/Markup.php +37 -0
  40. classes/Twig/Node.php +226 -0
  41. classes/Twig/Node/AutoEscape.php +39 -0
  42. classes/Twig/Node/Block.php +44 -0
  43. classes/Twig/Node/BlockReference.php +37 -0
  44. classes/Twig/Node/Body.php +19 -0
  45. classes/Twig/Node/Do.php +38 -0
  46. classes/Twig/Node/Embed.php +38 -0
  47. classes/Twig/Node/Expression.php +20 -0
  48. classes/Twig/Node/Expression/Array.php +86 -0
  49. classes/Twig/Node/Expression/AssignName.php +28 -0
  50. classes/Twig/Node/Expression/Binary.php +40 -0
  51. classes/Twig/Node/Expression/Binary/Add.php +18 -0
  52. classes/Twig/Node/Expression/Binary/And.php +18 -0
  53. classes/Twig/Node/Expression/Binary/BitwiseAnd.php +18 -0
  54. classes/Twig/Node/Expression/Binary/BitwiseOr.php +18 -0
  55. classes/Twig/Node/Expression/Binary/BitwiseXor.php +18 -0
  56. classes/Twig/Node/Expression/Binary/Concat.php +18 -0
  57. classes/Twig/Node/Expression/Binary/Div.php +18 -0
  58. classes/Twig/Node/Expression/Binary/EndsWith.php +30 -0
  59. classes/Twig/Node/Expression/Binary/Equal.php +17 -0
  60. classes/Twig/Node/Expression/Binary/FloorDiv.php +29 -0
  61. classes/Twig/Node/Expression/Binary/Greater.php +17 -0
  62. classes/Twig/Node/Expression/Binary/GreaterEqual.php +17 -0
  63. classes/Twig/Node/Expression/Binary/In.php +33 -0
  64. classes/Twig/Node/Expression/Binary/Less.php +17 -0
  65. classes/Twig/Node/Expression/Binary/LessEqual.php +17 -0
  66. classes/Twig/Node/Expression/Binary/Matches.php +28 -0
  67. classes/Twig/Node/Expression/Binary/Mod.php +18 -0
  68. classes/Twig/Node/Expression/Binary/Mul.php +18 -0
  69. classes/Twig/Node/Expression/Binary/NotEqual.php +17 -0
  70. classes/Twig/Node/Expression/Binary/NotIn.php +33 -0
  71. classes/Twig/Node/Expression/Binary/Or.php +18 -0
  72. classes/Twig/Node/Expression/Binary/Power.php +33 -0
  73. classes/Twig/Node/Expression/Binary/Range.php +33 -0
  74. classes/Twig/Node/Expression/Binary/StartsWith.php +28 -0
  75. classes/Twig/Node/Expression/Binary/Sub.php +18 -0
  76. classes/Twig/Node/Expression/BlockReference.php +51 -0
  77. classes/Twig/Node/Expression/Call.php +176 -0
  78. classes/Twig/Node/Expression/Conditional.php +31 -0
  79. classes/Twig/Node/Expression/Constant.php +23 -0
  80. classes/Twig/Node/Expression/ExtensionReference.php +33 -0
  81. classes/Twig/Node/Expression/Filter.php +36 -0
  82. classes/Twig/Node/Expression/Filter/Default.php +43 -0
  83. classes/Twig/Node/Expression/Function.php +35 -0
  84. classes/Twig/Node/Expression/GetAttr.php +53 -0
  85. classes/Twig/Node/Expression/MethodCall.php +41 -0
  86. classes/Twig/Node/Expression/Name.php +88 -0
  87. classes/Twig/Node/Expression/Parent.php +47 -0
  88. classes/Twig/Node/Expression/TempName.php +26 -0
  89. classes/Twig/Node/Expression/Test.php +32 -0
  90. classes/Twig/Node/Expression/Test/Constant.php +46 -0
  91. classes/Twig/Node/Expression/Test/Defined.php +54 -0
  92. classes/Twig/Node/Expression/Test/Divisibleby.php +33 -0
  93. classes/Twig/Node/Expression/Test/Even.php +32 -0
  94. classes/Twig/Node/Expression/Test/Null.php +31 -0
  95. classes/Twig/Node/Expression/Test/Odd.php +32 -0
  96. classes/Twig/Node/Expression/Test/Sameas.php +29 -0
  97. classes/Twig/Node/Expression/Unary.php +30 -0
  98. classes/Twig/Node/Expression/Unary/Neg.php +18 -0
  99. classes/Twig/Node/Expression/Unary/Not.php +18 -0
  100. classes/Twig/Node/Expression/Unary/Pos.php +18 -0
  101. classes/Twig/Node/Flush.php +36 -0
  102. classes/Twig/Node/For.php +112 -0
  103. classes/Twig/Node/ForLoop.php +55 -0
  104. classes/Twig/Node/If.php +66 -0
  105. classes/Twig/Node/Import.php +50 -0
  106. classes/Twig/Node/Include.php +99 -0
  107. classes/Twig/Node/Macro.php +96 -0
  108. classes/Twig/Node/Module.php +383 -0
  109. classes/Twig/Node/Print.php +39 -0
  110. classes/Twig/Node/Sandbox.php +47 -0
  111. classes/Twig/Node/SandboxedModule.php +60 -0
  112. classes/Twig/Node/SandboxedPrint.php +59 -0
  113. classes/Twig/Node/Set.php +101 -0
  114. classes/Twig/Node/SetTemp.php +35 -0
  115. classes/Twig/Node/Spaceless.php +40 -0
  116. classes/Twig/Node/Text.php +39 -0
  117. classes/Twig/NodeInterface.php +31 -0
  118. classes/Twig/NodeOutputInterface.php +19 -0
  119. classes/Twig/NodeTraverser.php +88 -0
  120. classes/Twig/NodeVisitor/Escaper.php +167 -0
  121. classes/Twig/NodeVisitor/Optimizer.php +246 -0
  122. classes/Twig/NodeVisitor/SafeAnalysis.php +139 -0
  123. classes/Twig/NodeVisitor/Sandbox.php +92 -0
  124. classes/Twig/NodeVisitorInterface.php +47 -0
  125. classes/Twig/Parser.php +390 -0
  126. classes/Twig/ParserInterface.php +31 -0
  127. classes/Twig/Sandbox/SecurityError.php +19 -0
  128. classes/Twig/Sandbox/SecurityPolicy.php +119 -0
  129. classes/Twig/Sandbox/SecurityPolicyInterface.php +24 -0
  130. classes/Twig/SimpleFilter.php +94 -0
  131. classes/Twig/SimpleFunction.php +84 -0
  132. classes/Twig/SimpleTest.php +46 -0
  133. classes/Twig/Template.php +485 -0
  134. classes/Twig/TemplateInterface.php +48 -0
  135. classes/Twig/Test.php +34 -0
  136. classes/Twig/TestCallableInterface.php +21 -0
  137. classes/Twig/TestInterface.php +26 -0
  138. classes/Twig/Token.php +216 -0
  139. classes/Twig/TokenParser.php +33 -0
  140. classes/Twig/TokenParser/AutoEscape.php +89 -0
  141. classes/Twig/TokenParser/Block.php +81 -0
  142. classes/Twig/TokenParser/Do.php +42 -0
  143. classes/Twig/TokenParser/Embed.php +66 -0
  144. classes/Twig/TokenParser/Extends.php +52 -0
  145. classes/Twig/TokenParser/Filter.php +61 -0
  146. classes/Twig/TokenParser/Flush.php +42 -0
  147. classes/Twig/TokenParser/For.php +135 -0
  148. classes/Twig/TokenParser/From.php +70 -0
  149. classes/Twig/TokenParser/If.php +94 -0
  150. classes/Twig/TokenParser/Import.php +49 -0
  151. classes/Twig/TokenParser/Include.php +75 -0
  152. classes/Twig/TokenParser/Macro.php +68 -0
  153. classes/Twig/TokenParser/Sandbox.php +68 -0
  154. classes/Twig/TokenParser/Set.php +83 -0
  155. classes/Twig/TokenParser/Spaceless.php +59 -0
  156. classes/Twig/TokenParser/Use.php +76 -0
  157. classes/Twig/TokenParserBroker.php +136 -0
  158. classes/Twig/TokenParserBrokerInterface.php +45 -0
  159. classes/Twig/TokenParserInterface.php +43 -0
  160. classes/Twig/TokenStream.php +156 -0
  161. classes/baseObject.php +22 -0
  162. classes/controller.php +232 -0
  163. classes/csvgenerator.php +35 -0
  164. classes/date.php +9 -0
  165. classes/db.php +141 -0
  166. classes/dispatcher.php +43 -0
  167. classes/errors.php +93 -0
  168. classes/field.php +518 -0
  169. classes/fieldAdapter.php +311 -0
  170. classes/filegenerator.php +52 -0
  171. classes/frame.php +471 -0
  172. classes/helper.php +38 -0
  173. classes/helpers/SxGeo.php +311 -0
  174. classes/helpers/mobileDetect.php +1458 -0
  175. classes/helpers/recapcha.php +47 -0
  176. classes/helpers/recaptchalib.php +298 -0
  177. classes/html.php +721 -0
  178. classes/installer.php +521 -0
classes/Twig/Autoloader.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Autoloads Twig classes.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Autoloader
18
+ {
19
+ /**
20
+ * Registers Twig_Autoloader as an SPL autoloader.
21
+ *
22
+ * @param bool $prepend Whether to prepend the autoloader or not.
23
+ */
24
+ public static function register($prepend = false)
25
+ {
26
+ if (version_compare(phpversion(), '5.3.0', '>=')) {
27
+ spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
28
+ } else {
29
+ spl_autoload_register(array(__CLASS__, 'autoload'));
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Handles autoloading of classes.
35
+ *
36
+ * @param string $class A class name.
37
+ */
38
+ public static function autoload($class)
39
+ {
40
+ if (0 !== strpos($class, 'Twig')) {
41
+ return;
42
+ }
43
+
44
+ if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
45
+ require $file;
46
+ }
47
+ }
48
+ }
classes/Twig/Compiler.php ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Compiles a node to PHP code.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Compiler implements Twig_CompilerInterface
19
+ {
20
+ protected $lastLine;
21
+ protected $source;
22
+ protected $indentation;
23
+ protected $env;
24
+ protected $debugInfo;
25
+ protected $sourceOffset;
26
+ protected $sourceLine;
27
+ protected $filename;
28
+
29
+ /**
30
+ * Constructor.
31
+ *
32
+ * @param Twig_Environment $env The twig environment instance
33
+ */
34
+ public function __construct(Twig_Environment $env)
35
+ {
36
+ $this->env = $env;
37
+ $this->debugInfo = array();
38
+ }
39
+
40
+ public function getFilename()
41
+ {
42
+ return $this->filename;
43
+ }
44
+
45
+ /**
46
+ * Returns the environment instance related to this compiler.
47
+ *
48
+ * @return Twig_Environment The environment instance
49
+ */
50
+ public function getEnvironment()
51
+ {
52
+ return $this->env;
53
+ }
54
+
55
+ /**
56
+ * Gets the current PHP code after compilation.
57
+ *
58
+ * @return string The PHP code
59
+ */
60
+ public function getSource()
61
+ {
62
+ return $this->source;
63
+ }
64
+
65
+ /**
66
+ * Compiles a node.
67
+ *
68
+ * @param Twig_NodeInterface $node The node to compile
69
+ * @param int $indentation The current indentation
70
+ *
71
+ * @return Twig_Compiler The current compiler instance
72
+ */
73
+ public function compile(Twig_NodeInterface $node, $indentation = 0)
74
+ {
75
+ $this->lastLine = null;
76
+ $this->source = '';
77
+ $this->sourceOffset = 0;
78
+ // source code starts at 1 (as we then increment it when we encounter new lines)
79
+ $this->sourceLine = 1;
80
+ $this->indentation = $indentation;
81
+
82
+ if ($node instanceof Twig_Node_Module) {
83
+ $this->filename = $node->getAttribute('filename');
84
+ }
85
+
86
+ $node->compile($this);
87
+
88
+ return $this;
89
+ }
90
+
91
+ public function subcompile(Twig_NodeInterface $node, $raw = true)
92
+ {
93
+ if (false === $raw) {
94
+ $this->addIndentation();
95
+ }
96
+
97
+ $node->compile($this);
98
+
99
+ return $this;
100
+ }
101
+
102
+ /**
103
+ * Adds a raw string to the compiled code.
104
+ *
105
+ * @param string $string The string
106
+ *
107
+ * @return Twig_Compiler The current compiler instance
108
+ */
109
+ public function raw($string)
110
+ {
111
+ $this->source .= $string;
112
+
113
+ return $this;
114
+ }
115
+
116
+ /**
117
+ * Writes a string to the compiled code by adding indentation.
118
+ *
119
+ * @return Twig_Compiler The current compiler instance
120
+ */
121
+ public function write()
122
+ {
123
+ $strings = func_get_args();
124
+ foreach ($strings as $string) {
125
+ $this->addIndentation();
126
+ $this->source .= $string;
127
+ }
128
+
129
+ return $this;
130
+ }
131
+
132
+ /**
133
+ * Appends an indentation to the current PHP code after compilation.
134
+ *
135
+ * @return Twig_Compiler The current compiler instance
136
+ */
137
+ public function addIndentation()
138
+ {
139
+ $this->source .= str_repeat(' ', $this->indentation * 4);
140
+
141
+ return $this;
142
+ }
143
+
144
+ /**
145
+ * Adds a quoted string to the compiled code.
146
+ *
147
+ * @param string $value The string
148
+ *
149
+ * @return Twig_Compiler The current compiler instance
150
+ */
151
+ public function string($value)
152
+ {
153
+ $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
154
+
155
+ return $this;
156
+ }
157
+
158
+ /**
159
+ * Returns a PHP representation of a given value.
160
+ *
161
+ * @param mixed $value The value to convert
162
+ *
163
+ * @return Twig_Compiler The current compiler instance
164
+ */
165
+ public function repr($value)
166
+ {
167
+ if (is_int($value) || is_float($value)) {
168
+ if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
169
+ setlocale(LC_NUMERIC, 'C');
170
+ }
171
+
172
+ $this->raw($value);
173
+
174
+ if (false !== $locale) {
175
+ setlocale(LC_NUMERIC, $locale);
176
+ }
177
+ } elseif (null === $value) {
178
+ $this->raw('null');
179
+ } elseif (is_bool($value)) {
180
+ $this->raw($value ? 'true' : 'false');
181
+ } elseif (is_array($value)) {
182
+ $this->raw('array(');
183
+ $first = true;
184
+ foreach ($value as $key => $value) {
185
+ if (!$first) {
186
+ $this->raw(', ');
187
+ }
188
+ $first = false;
189
+ $this->repr($key);
190
+ $this->raw(' => ');
191
+ $this->repr($value);
192
+ }
193
+ $this->raw(')');
194
+ } else {
195
+ $this->string($value);
196
+ }
197
+
198
+ return $this;
199
+ }
200
+
201
+ /**
202
+ * Adds debugging information.
203
+ *
204
+ * @param Twig_NodeInterface $node The related twig node
205
+ *
206
+ * @return Twig_Compiler The current compiler instance
207
+ */
208
+ public function addDebugInfo(Twig_NodeInterface $node)
209
+ {
210
+ if ($node->getLine() != $this->lastLine) {
211
+ $this->write(sprintf("// line %d\n", $node->getLine()));
212
+
213
+ // when mbstring.func_overload is set to 2
214
+ // mb_substr_count() replaces substr_count()
215
+ // but they have different signatures!
216
+ if (((int) ini_get('mbstring.func_overload')) & 2) {
217
+ // this is much slower than the "right" version
218
+ $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
219
+ } else {
220
+ $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
221
+ }
222
+ $this->sourceOffset = strlen($this->source);
223
+ $this->debugInfo[$this->sourceLine] = $node->getLine();
224
+
225
+ $this->lastLine = $node->getLine();
226
+ }
227
+
228
+ return $this;
229
+ }
230
+
231
+ public function getDebugInfo()
232
+ {
233
+ return $this->debugInfo;
234
+ }
235
+
236
+ /**
237
+ * Indents the generated code.
238
+ *
239
+ * @param int $step The number of indentation to add
240
+ *
241
+ * @return Twig_Compiler The current compiler instance
242
+ */
243
+ public function indent($step = 1)
244
+ {
245
+ $this->indentation += $step;
246
+
247
+ return $this;
248
+ }
249
+
250
+ /**
251
+ * Outdents the generated code.
252
+ *
253
+ * @param int $step The number of indentation to remove
254
+ *
255
+ * @return Twig_Compiler The current compiler instance
256
+ *
257
+ * @throws LogicException When trying to outdent too much so the indentation would become negative
258
+ */
259
+ public function outdent($step = 1)
260
+ {
261
+ // can't outdent by more steps than the current indentation level
262
+ if ($this->indentation < $step) {
263
+ throw new LogicException('Unable to call outdent() as the indentation would become negative');
264
+ }
265
+
266
+ $this->indentation -= $step;
267
+
268
+ return $this;
269
+ }
270
+ }
classes/Twig/CompilerInterface.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface implemented by compiler classes.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ *
17
+ * @deprecated since 1.12 (to be removed in 3.0)
18
+ */
19
+ interface Twig_CompilerInterface
20
+ {
21
+ /**
22
+ * Compiles a node.
23
+ *
24
+ * @param Twig_NodeInterface $node The node to compile
25
+ *
26
+ * @return Twig_CompilerInterface The current compiler instance
27
+ */
28
+ public function compile(Twig_NodeInterface $node);
29
+
30
+ /**
31
+ * Gets the current PHP code after compilation.
32
+ *
33
+ * @return string The PHP code
34
+ */
35
+ public function getSource();
36
+ }
classes/Twig/Environment.php ADDED
@@ -0,0 +1,1254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Stores the Twig configuration.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Environment
18
+ {
19
+ const VERSION = '1.16.0';
20
+
21
+ protected $charset;
22
+ protected $loader;
23
+ protected $debug;
24
+ protected $autoReload;
25
+ protected $cache;
26
+ protected $lexer;
27
+ protected $parser;
28
+ protected $compiler;
29
+ protected $baseTemplateClass;
30
+ protected $extensions;
31
+ protected $parsers;
32
+ protected $visitors;
33
+ protected $filters;
34
+ protected $tests;
35
+ protected $functions;
36
+ protected $globals;
37
+ protected $runtimeInitialized;
38
+ protected $extensionInitialized;
39
+ protected $loadedTemplates;
40
+ protected $strictVariables;
41
+ protected $unaryOperators;
42
+ protected $binaryOperators;
43
+ protected $templateClassPrefix = '__TwigTemplate_';
44
+ protected $functionCallbacks;
45
+ protected $filterCallbacks;
46
+ protected $staging;
47
+
48
+ /**
49
+ * Constructor.
50
+ *
51
+ * Available options:
52
+ *
53
+ * * debug: When set to true, it automatically set "auto_reload" to true as
54
+ * well (default to false).
55
+ *
56
+ * * charset: The charset used by the templates (default to UTF-8).
57
+ *
58
+ * * base_template_class: The base template class to use for generated
59
+ * templates (default to Twig_Template).
60
+ *
61
+ * * cache: An absolute path where to store the compiled templates, or
62
+ * false to disable compilation cache (default).
63
+ *
64
+ * * auto_reload: Whether to reload the template if the original source changed.
65
+ * If you don't provide the auto_reload option, it will be
66
+ * determined automatically based on the debug value.
67
+ *
68
+ * * strict_variables: Whether to ignore invalid variables in templates
69
+ * (default to false).
70
+ *
71
+ * * autoescape: Whether to enable auto-escaping (default to html):
72
+ * * false: disable auto-escaping
73
+ * * true: equivalent to html
74
+ * * html, js: set the autoescaping to one of the supported strategies
75
+ * * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
76
+ *
77
+ * * optimizations: A flag that indicates which optimizations to apply
78
+ * (default to -1 which means that all optimizations are enabled;
79
+ * set it to 0 to disable).
80
+ *
81
+ * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
82
+ * @param array $options An array of options
83
+ */
84
+ public function __construct(Twig_LoaderInterface $loader = null, $options = array())
85
+ {
86
+ if (null !== $loader) {
87
+ $this->setLoader($loader);
88
+ }
89
+
90
+ $options = array_merge(array(
91
+ 'debug' => false,
92
+ 'charset' => 'UTF-8',
93
+ 'base_template_class' => 'Twig_Template',
94
+ 'strict_variables' => false,
95
+ 'autoescape' => 'html',
96
+ 'cache' => false,
97
+ 'auto_reload' => null,
98
+ 'optimizations' => -1,
99
+ ), $options);
100
+
101
+ $this->debug = (bool) $options['debug'];
102
+ $this->charset = strtoupper($options['charset']);
103
+ $this->baseTemplateClass = $options['base_template_class'];
104
+ $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
105
+ $this->strictVariables = (bool) $options['strict_variables'];
106
+ $this->runtimeInitialized = false;
107
+ $this->setCache($options['cache']);
108
+ $this->functionCallbacks = array();
109
+ $this->filterCallbacks = array();
110
+
111
+ $this->addExtension(new Twig_Extension_Core());
112
+ $this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
113
+ $this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
114
+ $this->extensionInitialized = false;
115
+ $this->staging = new Twig_Extension_Staging();
116
+ }
117
+
118
+ /**
119
+ * Gets the base template class for compiled templates.
120
+ *
121
+ * @return string The base template class name
122
+ */
123
+ public function getBaseTemplateClass()
124
+ {
125
+ return $this->baseTemplateClass;
126
+ }
127
+
128
+ /**
129
+ * Sets the base template class for compiled templates.
130
+ *
131
+ * @param string $class The base template class name
132
+ */
133
+ public function setBaseTemplateClass($class)
134
+ {
135
+ $this->baseTemplateClass = $class;
136
+ }
137
+
138
+ /**
139
+ * Enables debugging mode.
140
+ */
141
+ public function enableDebug()
142
+ {
143
+ $this->debug = true;
144
+ }
145
+
146
+ /**
147
+ * Disables debugging mode.
148
+ */
149
+ public function disableDebug()
150
+ {
151
+ $this->debug = false;
152
+ }
153
+
154
+ /**
155
+ * Checks if debug mode is enabled.
156
+ *
157
+ * @return bool true if debug mode is enabled, false otherwise
158
+ */
159
+ public function isDebug()
160
+ {
161
+ return $this->debug;
162
+ }
163
+
164
+ /**
165
+ * Enables the auto_reload option.
166
+ */
167
+ public function enableAutoReload()
168
+ {
169
+ $this->autoReload = true;
170
+ }
171
+
172
+ /**
173
+ * Disables the auto_reload option.
174
+ */
175
+ public function disableAutoReload()
176
+ {
177
+ $this->autoReload = false;
178
+ }
179
+
180
+ /**
181
+ * Checks if the auto_reload option is enabled.
182
+ *
183
+ * @return bool true if auto_reload is enabled, false otherwise
184
+ */
185
+ public function isAutoReload()
186
+ {
187
+ return $this->autoReload;
188
+ }
189
+
190
+ /**
191
+ * Enables the strict_variables option.
192
+ */
193
+ public function enableStrictVariables()
194
+ {
195
+ $this->strictVariables = true;
196
+ }
197
+
198
+ /**
199
+ * Disables the strict_variables option.
200
+ */
201
+ public function disableStrictVariables()
202
+ {
203
+ $this->strictVariables = false;
204
+ }
205
+
206
+ /**
207
+ * Checks if the strict_variables option is enabled.
208
+ *
209
+ * @return bool true if strict_variables is enabled, false otherwise
210
+ */
211
+ public function isStrictVariables()
212
+ {
213
+ return $this->strictVariables;
214
+ }
215
+
216
+ /**
217
+ * Gets the cache directory or false if cache is disabled.
218
+ *
219
+ * @return string|false
220
+ */
221
+ public function getCache()
222
+ {
223
+ return $this->cache;
224
+ }
225
+
226
+ /**
227
+ * Sets the cache directory or false if cache is disabled.
228
+ *
229
+ * @param string|false $cache The absolute path to the compiled templates,
230
+ * or false to disable cache
231
+ */
232
+ public function setCache($cache)
233
+ {
234
+ $this->cache = $cache ? $cache : false;
235
+ }
236
+
237
+ /**
238
+ * Gets the cache filename for a given template.
239
+ *
240
+ * @param string $name The template name
241
+ *
242
+ * @return string|false The cache file name or false when caching is disabled
243
+ */
244
+ public function getCacheFilename($name)
245
+ {
246
+ if (false === $this->cache) {
247
+ return false;
248
+ }
249
+
250
+ $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
251
+
252
+ return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php';
253
+ }
254
+
255
+ /**
256
+ * Gets the template class associated with the given string.
257
+ *
258
+ * @param string $name The name for which to calculate the template class name
259
+ * @param int $index The index if it is an embedded template
260
+ *
261
+ * @return string The template class name
262
+ */
263
+ public function getTemplateClass($name, $index = null)
264
+ {
265
+ return $this->templateClassPrefix.hash('sha256', $this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
266
+ }
267
+
268
+ /**
269
+ * Gets the template class prefix.
270
+ *
271
+ * @return string The template class prefix
272
+ */
273
+ public function getTemplateClassPrefix()
274
+ {
275
+ return $this->templateClassPrefix;
276
+ }
277
+
278
+ /**
279
+ * Renders a template.
280
+ *
281
+ * @param string $name The template name
282
+ * @param array $context An array of parameters to pass to the template
283
+ *
284
+ * @return string The rendered template
285
+ *
286
+ * @throws Twig_Error_Loader When the template cannot be found
287
+ * @throws Twig_Error_Syntax When an error occurred during compilation
288
+ * @throws Twig_Error_Runtime When an error occurred during rendering
289
+ */
290
+ public function render($name, array $context = array())
291
+ {
292
+ return $this->loadTemplate($name)->render($context);
293
+ }
294
+
295
+ /**
296
+ * Displays a template.
297
+ *
298
+ * @param string $name The template name
299
+ * @param array $context An array of parameters to pass to the template
300
+ *
301
+ * @throws Twig_Error_Loader When the template cannot be found
302
+ * @throws Twig_Error_Syntax When an error occurred during compilation
303
+ * @throws Twig_Error_Runtime When an error occurred during rendering
304
+ */
305
+ public function display($name, array $context = array())
306
+ {
307
+ $this->loadTemplate($name)->display($context);
308
+ }
309
+
310
+ /**
311
+ * Loads a template by name.
312
+ *
313
+ * @param string $name The template name
314
+ * @param int $index The index if it is an embedded template
315
+ *
316
+ * @return Twig_TemplateInterface A template instance representing the given template name
317
+ *
318
+ * @throws Twig_Error_Loader When the template cannot be found
319
+ * @throws Twig_Error_Syntax When an error occurred during compilation
320
+ */
321
+ public function loadTemplate($name, $index = null)
322
+ {
323
+ $cls = $this->getTemplateClass($name, $index);
324
+
325
+ if (isset($this->loadedTemplates[$cls])) {
326
+ return $this->loadedTemplates[$cls];
327
+ }
328
+
329
+ if (!class_exists($cls, false)) {
330
+ if (false === $cache = $this->getCacheFilename($name)) {
331
+ eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
332
+ } else {
333
+ if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
334
+ $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
335
+ }
336
+
337
+ require_once $cache;
338
+ }
339
+ }
340
+
341
+ if (!$this->runtimeInitialized) {
342
+ $this->initRuntime();
343
+ }
344
+
345
+ return $this->loadedTemplates[$cls] = new $cls($this);
346
+ }
347
+
348
+ /**
349
+ * Returns true if the template is still fresh.
350
+ *
351
+ * Besides checking the loader for freshness information,
352
+ * this method also checks if the enabled extensions have
353
+ * not changed.
354
+ *
355
+ * @param string $name The template name
356
+ * @param timestamp $time The last modification time of the cached template
357
+ *
358
+ * @return bool true if the template is fresh, false otherwise
359
+ */
360
+ public function isTemplateFresh($name, $time)
361
+ {
362
+ foreach ($this->extensions as $extension) {
363
+ $r = new ReflectionObject($extension);
364
+ if (filemtime($r->getFileName()) > $time) {
365
+ return false;
366
+ }
367
+ }
368
+
369
+ return $this->getLoader()->isFresh($name, $time);
370
+ }
371
+
372
+ /**
373
+ * Tries to load a template consecutively from an array.
374
+ *
375
+ * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array
376
+ * of templates where each is tried to be loaded.
377
+ *
378
+ * @param string|Twig_Template|array $names A template or an array of templates to try consecutively
379
+ *
380
+ * @return Twig_Template
381
+ *
382
+ * @throws Twig_Error_Loader When none of the templates can be found
383
+ * @throws Twig_Error_Syntax When an error occurred during compilation
384
+ */
385
+ public function resolveTemplate($names)
386
+ {
387
+ if (!is_array($names)) {
388
+ $names = array($names);
389
+ }
390
+
391
+ foreach ($names as $name) {
392
+ if ($name instanceof Twig_Template) {
393
+ return $name;
394
+ }
395
+
396
+ try {
397
+ return $this->loadTemplate($name);
398
+ } catch (Twig_Error_Loader $e) {
399
+ }
400
+ }
401
+
402
+ if (1 === count($names)) {
403
+ throw $e;
404
+ }
405
+
406
+ throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
407
+ }
408
+
409
+ /**
410
+ * Clears the internal template cache.
411
+ */
412
+ public function clearTemplateCache()
413
+ {
414
+ $this->loadedTemplates = array();
415
+ }
416
+
417
+ /**
418
+ * Clears the template cache files on the filesystem.
419
+ */
420
+ public function clearCacheFiles()
421
+ {
422
+ if (false === $this->cache) {
423
+ return;
424
+ }
425
+
426
+ foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
427
+ if ($file->isFile()) {
428
+ @unlink($file->getPathname());
429
+ }
430
+ }
431
+ }
432
+
433
+ /**
434
+ * Gets the Lexer instance.
435
+ *
436
+ * @return Twig_LexerInterface A Twig_LexerInterface instance
437
+ */
438
+ public function getLexer()
439
+ {
440
+ if (null === $this->lexer) {
441
+ $this->lexer = new Twig_Lexer($this);
442
+ }
443
+
444
+ return $this->lexer;
445
+ }
446
+
447
+ /**
448
+ * Sets the Lexer instance.
449
+ *
450
+ * @param Twig_LexerInterface A Twig_LexerInterface instance
451
+ */
452
+ public function setLexer(Twig_LexerInterface $lexer)
453
+ {
454
+ $this->lexer = $lexer;
455
+ }
456
+
457
+ /**
458
+ * Tokenizes a source code.
459
+ *
460
+ * @param string $source The template source code
461
+ * @param string $name The template name
462
+ *
463
+ * @return Twig_TokenStream A Twig_TokenStream instance
464
+ *
465
+ * @throws Twig_Error_Syntax When the code is syntactically wrong
466
+ */
467
+ public function tokenize($source, $name = null)
468
+ {
469
+ return $this->getLexer()->tokenize($source, $name);
470
+ }
471
+
472
+ /**
473
+ * Gets the Parser instance.
474
+ *
475
+ * @return Twig_ParserInterface A Twig_ParserInterface instance
476
+ */
477
+ public function getParser()
478
+ {
479
+ if (null === $this->parser) {
480
+ $this->parser = new Twig_Parser($this);
481
+ }
482
+
483
+ return $this->parser;
484
+ }
485
+
486
+ /**
487
+ * Sets the Parser instance.
488
+ *
489
+ * @param Twig_ParserInterface A Twig_ParserInterface instance
490
+ */
491
+ public function setParser(Twig_ParserInterface $parser)
492
+ {
493
+ $this->parser = $parser;
494
+ }
495
+
496
+ /**
497
+ * Converts a token stream to a node tree.
498
+ *
499
+ * @param Twig_TokenStream $stream A token stream instance
500
+ *
501
+ * @return Twig_Node_Module A node tree
502
+ *
503
+ * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
504
+ */
505
+ public function parse(Twig_TokenStream $stream)
506
+ {
507
+ return $this->getParser()->parse($stream);
508
+ }
509
+
510
+ /**
511
+ * Gets the Compiler instance.
512
+ *
513
+ * @return Twig_CompilerInterface A Twig_CompilerInterface instance
514
+ */
515
+ public function getCompiler()
516
+ {
517
+ if (null === $this->compiler) {
518
+ $this->compiler = new Twig_Compiler($this);
519
+ }
520
+
521
+ return $this->compiler;
522
+ }
523
+
524
+ /**
525
+ * Sets the Compiler instance.
526
+ *
527
+ * @param Twig_CompilerInterface $compiler A Twig_CompilerInterface instance
528
+ */
529
+ public function setCompiler(Twig_CompilerInterface $compiler)
530
+ {
531
+ $this->compiler = $compiler;
532
+ }
533
+
534
+ /**
535
+ * Compiles a node and returns the PHP code.
536
+ *
537
+ * @param Twig_NodeInterface $node A Twig_NodeInterface instance
538
+ *
539
+ * @return string The compiled PHP source code
540
+ */
541
+ public function compile(Twig_NodeInterface $node)
542
+ {
543
+ return $this->getCompiler()->compile($node)->getSource();
544
+ }
545
+
546
+ /**
547
+ * Compiles a template source code.
548
+ *
549
+ * @param string $source The template source code
550
+ * @param string $name The template name
551
+ *
552
+ * @return string The compiled PHP source code
553
+ *
554
+ * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling
555
+ */
556
+ public function compileSource($source, $name = null)
557
+ {
558
+ try {
559
+ return $this->compile($this->parse($this->tokenize($source, $name)));
560
+ } catch (Twig_Error $e) {
561
+ $e->setTemplateFile($name);
562
+ throw $e;
563
+ } catch (Exception $e) {
564
+ throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e);
565
+ }
566
+ }
567
+
568
+ /**
569
+ * Sets the Loader instance.
570
+ *
571
+ * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
572
+ */
573
+ public function setLoader(Twig_LoaderInterface $loader)
574
+ {
575
+ $this->loader = $loader;
576
+ }
577
+
578
+ /**
579
+ * Gets the Loader instance.
580
+ *
581
+ * @return Twig_LoaderInterface A Twig_LoaderInterface instance
582
+ */
583
+ public function getLoader()
584
+ {
585
+ if (null === $this->loader) {
586
+ throw new LogicException('You must set a loader first.');
587
+ }
588
+
589
+ return $this->loader;
590
+ }
591
+
592
+ /**
593
+ * Sets the default template charset.
594
+ *
595
+ * @param string $charset The default charset
596
+ */
597
+ public function setCharset($charset)
598
+ {
599
+ $this->charset = strtoupper($charset);
600
+ }
601
+
602
+ /**
603
+ * Gets the default template charset.
604
+ *
605
+ * @return string The default charset
606
+ */
607
+ public function getCharset()
608
+ {
609
+ return $this->charset;
610
+ }
611
+
612
+ /**
613
+ * Initializes the runtime environment.
614
+ */
615
+ public function initRuntime()
616
+ {
617
+ $this->runtimeInitialized = true;
618
+
619
+ foreach ($this->getExtensions() as $extension) {
620
+ $extension->initRuntime($this);
621
+ }
622
+ }
623
+
624
+ /**
625
+ * Returns true if the given extension is registered.
626
+ *
627
+ * @param string $name The extension name
628
+ *
629
+ * @return bool Whether the extension is registered or not
630
+ */
631
+ public function hasExtension($name)
632
+ {
633
+ return isset($this->extensions[$name]);
634
+ }
635
+
636
+ /**
637
+ * Gets an extension by name.
638
+ *
639
+ * @param string $name The extension name
640
+ *
641
+ * @return Twig_ExtensionInterface A Twig_ExtensionInterface instance
642
+ */
643
+ public function getExtension($name)
644
+ {
645
+ if (!isset($this->extensions[$name])) {
646
+ throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $name));
647
+ }
648
+
649
+ return $this->extensions[$name];
650
+ }
651
+
652
+ /**
653
+ * Registers an extension.
654
+ *
655
+ * @param Twig_ExtensionInterface $extension A Twig_ExtensionInterface instance
656
+ */
657
+ public function addExtension(Twig_ExtensionInterface $extension)
658
+ {
659
+ if ($this->extensionInitialized) {
660
+ throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
661
+ }
662
+
663
+ $this->extensions[$extension->getName()] = $extension;
664
+ }
665
+
666
+ /**
667
+ * Removes an extension by name.
668
+ *
669
+ * This method is deprecated and you should not use it.
670
+ *
671
+ * @param string $name The extension name
672
+ *
673
+ * @deprecated since 1.12 (to be removed in 2.0)
674
+ */
675
+ public function removeExtension($name)
676
+ {
677
+ if ($this->extensionInitialized) {
678
+ throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
679
+ }
680
+
681
+ unset($this->extensions[$name]);
682
+ }
683
+
684
+ /**
685
+ * Registers an array of extensions.
686
+ *
687
+ * @param array $extensions An array of extensions
688
+ */
689
+ public function setExtensions(array $extensions)
690
+ {
691
+ foreach ($extensions as $extension) {
692
+ $this->addExtension($extension);
693
+ }
694
+ }
695
+
696
+ /**
697
+ * Returns all registered extensions.
698
+ *
699
+ * @return array An array of extensions
700
+ */
701
+ public function getExtensions()
702
+ {
703
+ return $this->extensions;
704
+ }
705
+
706
+ /**
707
+ * Registers a Token Parser.
708
+ *
709
+ * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
710
+ */
711
+ public function addTokenParser(Twig_TokenParserInterface $parser)
712
+ {
713
+ if ($this->extensionInitialized) {
714
+ throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
715
+ }
716
+
717
+ $this->staging->addTokenParser($parser);
718
+ }
719
+
720
+ /**
721
+ * Gets the registered Token Parsers.
722
+ *
723
+ * @return Twig_TokenParserBrokerInterface A broker containing token parsers
724
+ */
725
+ public function getTokenParsers()
726
+ {
727
+ if (!$this->extensionInitialized) {
728
+ $this->initExtensions();
729
+ }
730
+
731
+ return $this->parsers;
732
+ }
733
+
734
+ /**
735
+ * Gets registered tags.
736
+ *
737
+ * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
738
+ *
739
+ * @return Twig_TokenParserInterface[] An array of Twig_TokenParserInterface instances
740
+ */
741
+ public function getTags()
742
+ {
743
+ $tags = array();
744
+ foreach ($this->getTokenParsers()->getParsers() as $parser) {
745
+ if ($parser instanceof Twig_TokenParserInterface) {
746
+ $tags[$parser->getTag()] = $parser;
747
+ }
748
+ }
749
+
750
+ return $tags;
751
+ }
752
+
753
+ /**
754
+ * Registers a Node Visitor.
755
+ *
756
+ * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
757
+ */
758
+ public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
759
+ {
760
+ if ($this->extensionInitialized) {
761
+ throw new LogicException('Unable to add a node visitor as extensions have already been initialized.');
762
+ }
763
+
764
+ $this->staging->addNodeVisitor($visitor);
765
+ }
766
+
767
+ /**
768
+ * Gets the registered Node Visitors.
769
+ *
770
+ * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
771
+ */
772
+ public function getNodeVisitors()
773
+ {
774
+ if (!$this->extensionInitialized) {
775
+ $this->initExtensions();
776
+ }
777
+
778
+ return $this->visitors;
779
+ }
780
+
781
+ /**
782
+ * Registers a Filter.
783
+ *
784
+ * @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance
785
+ * @param Twig_FilterInterface|Twig_SimpleFilter $filter A Twig_FilterInterface instance or a Twig_SimpleFilter instance
786
+ */
787
+ public function addFilter($name, $filter = null)
788
+ {
789
+ if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
790
+ throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
791
+ }
792
+
793
+ if ($name instanceof Twig_SimpleFilter) {
794
+ $filter = $name;
795
+ $name = $filter->getName();
796
+ }
797
+
798
+ if ($this->extensionInitialized) {
799
+ throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
800
+ }
801
+
802
+ $this->staging->addFilter($name, $filter);
803
+ }
804
+
805
+ /**
806
+ * Get a filter by name.
807
+ *
808
+ * Subclasses may override this method and load filters differently;
809
+ * so no list of filters is available.
810
+ *
811
+ * @param string $name The filter name
812
+ *
813
+ * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist
814
+ */
815
+ public function getFilter($name)
816
+ {
817
+ if (!$this->extensionInitialized) {
818
+ $this->initExtensions();
819
+ }
820
+
821
+ if (isset($this->filters[$name])) {
822
+ return $this->filters[$name];
823
+ }
824
+
825
+ foreach ($this->filters as $pattern => $filter) {
826
+ $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
827
+
828
+ if ($count) {
829
+ if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
830
+ array_shift($matches);
831
+ $filter->setArguments($matches);
832
+
833
+ return $filter;
834
+ }
835
+ }
836
+ }
837
+
838
+ foreach ($this->filterCallbacks as $callback) {
839
+ if (false !== $filter = call_user_func($callback, $name)) {
840
+ return $filter;
841
+ }
842
+ }
843
+
844
+ return false;
845
+ }
846
+
847
+ public function registerUndefinedFilterCallback($callable)
848
+ {
849
+ $this->filterCallbacks[] = $callable;
850
+ }
851
+
852
+ /**
853
+ * Gets the registered Filters.
854
+ *
855
+ * Be warned that this method cannot return filters defined with registerUndefinedFunctionCallback.
856
+ *
857
+ * @return Twig_FilterInterface[] An array of Twig_FilterInterface instances
858
+ *
859
+ * @see registerUndefinedFilterCallback
860
+ */
861
+ public function getFilters()
862
+ {
863
+ if (!$this->extensionInitialized) {
864
+ $this->initExtensions();
865
+ }
866
+
867
+ return $this->filters;
868
+ }
869
+
870
+ /**
871
+ * Registers a Test.
872
+ *
873
+ * @param string|Twig_SimpleTest $name The test name or a Twig_SimpleTest instance
874
+ * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance
875
+ */
876
+ public function addTest($name, $test = null)
877
+ {
878
+ if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
879
+ throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
880
+ }
881
+
882
+ if ($name instanceof Twig_SimpleTest) {
883
+ $test = $name;
884
+ $name = $test->getName();
885
+ }
886
+
887
+ if ($this->extensionInitialized) {
888
+ throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
889
+ }
890
+
891
+ $this->staging->addTest($name, $test);
892
+ }
893
+
894
+ /**
895
+ * Gets the registered Tests.
896
+ *
897
+ * @return Twig_TestInterface[] An array of Twig_TestInterface instances
898
+ */
899
+ public function getTests()
900
+ {
901
+ if (!$this->extensionInitialized) {
902
+ $this->initExtensions();
903
+ }
904
+
905
+ return $this->tests;
906
+ }
907
+
908
+ /**
909
+ * Gets a test by name.
910
+ *
911
+ * @param string $name The test name
912
+ *
913
+ * @return Twig_Test|false A Twig_Test instance or false if the test does not exist
914
+ */
915
+ public function getTest($name)
916
+ {
917
+ if (!$this->extensionInitialized) {
918
+ $this->initExtensions();
919
+ }
920
+
921
+ if (isset($this->tests[$name])) {
922
+ return $this->tests[$name];
923
+ }
924
+
925
+ return false;
926
+ }
927
+
928
+ /**
929
+ * Registers a Function.
930
+ *
931
+ * @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance
932
+ * @param Twig_FunctionInterface|Twig_SimpleFunction $function A Twig_FunctionInterface instance or a Twig_SimpleFunction instance
933
+ */
934
+ public function addFunction($name, $function = null)
935
+ {
936
+ if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
937
+ throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
938
+ }
939
+
940
+ if ($name instanceof Twig_SimpleFunction) {
941
+ $function = $name;
942
+ $name = $function->getName();
943
+ }
944
+
945
+ if ($this->extensionInitialized) {
946
+ throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
947
+ }
948
+
949
+ $this->staging->addFunction($name, $function);
950
+ }
951
+
952
+ /**
953
+ * Get a function by name.
954
+ *
955
+ * Subclasses may override this method and load functions differently;
956
+ * so no list of functions is available.
957
+ *
958
+ * @param string $name function name
959
+ *
960
+ * @return Twig_Function|false A Twig_Function instance or false if the function does not exist
961
+ */
962
+ public function getFunction($name)
963
+ {
964
+ if (!$this->extensionInitialized) {
965
+ $this->initExtensions();
966
+ }
967
+
968
+ if (isset($this->functions[$name])) {
969
+ return $this->functions[$name];
970
+ }
971
+
972
+ foreach ($this->functions as $pattern => $function) {
973
+ $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
974
+
975
+ if ($count) {
976
+ if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
977
+ array_shift($matches);
978
+ $function->setArguments($matches);
979
+
980
+ return $function;
981
+ }
982
+ }
983
+ }
984
+
985
+ foreach ($this->functionCallbacks as $callback) {
986
+ if (false !== $function = call_user_func($callback, $name)) {
987
+ return $function;
988
+ }
989
+ }
990
+
991
+ return false;
992
+ }
993
+
994
+ public function registerUndefinedFunctionCallback($callable)
995
+ {
996
+ $this->functionCallbacks[] = $callable;
997
+ }
998
+
999
+ /**
1000
+ * Gets registered functions.
1001
+ *
1002
+ * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
1003
+ *
1004
+ * @return Twig_FunctionInterface[] An array of Twig_FunctionInterface instances
1005
+ *
1006
+ * @see registerUndefinedFunctionCallback
1007
+ */
1008
+ public function getFunctions()
1009
+ {
1010
+ if (!$this->extensionInitialized) {
1011
+ $this->initExtensions();
1012
+ }
1013
+
1014
+ return $this->functions;
1015
+ }
1016
+
1017
+ /**
1018
+ * Registers a Global.
1019
+ *
1020
+ * New globals can be added before compiling or rendering a template;
1021
+ * but after, you can only update existing globals.
1022
+ *
1023
+ * @param string $name The global name
1024
+ * @param mixed $value The global value
1025
+ */
1026
+ public function addGlobal($name, $value)
1027
+ {
1028
+ if ($this->extensionInitialized || $this->runtimeInitialized) {
1029
+ if (null === $this->globals) {
1030
+ $this->globals = $this->initGlobals();
1031
+ }
1032
+
1033
+ /* This condition must be uncommented in Twig 2.0
1034
+ if (!array_key_exists($name, $this->globals)) {
1035
+ throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
1036
+ }
1037
+ */
1038
+ }
1039
+
1040
+ if ($this->extensionInitialized || $this->runtimeInitialized) {
1041
+ // update the value
1042
+ $this->globals[$name] = $value;
1043
+ } else {
1044
+ $this->staging->addGlobal($name, $value);
1045
+ }
1046
+ }
1047
+
1048
+ /**
1049
+ * Gets the registered Globals.
1050
+ *
1051
+ * @return array An array of globals
1052
+ */
1053
+ public function getGlobals()
1054
+ {
1055
+ if (!$this->runtimeInitialized && !$this->extensionInitialized) {
1056
+ return $this->initGlobals();
1057
+ }
1058
+
1059
+ if (null === $this->globals) {
1060
+ $this->globals = $this->initGlobals();
1061
+ }
1062
+
1063
+ return $this->globals;
1064
+ }
1065
+
1066
+ /**
1067
+ * Merges a context with the defined globals.
1068
+ *
1069
+ * @param array $context An array representing the context
1070
+ *
1071
+ * @return array The context merged with the globals
1072
+ */
1073
+ public function mergeGlobals(array $context)
1074
+ {
1075
+ // we don't use array_merge as the context being generally
1076
+ // bigger than globals, this code is faster.
1077
+ foreach ($this->getGlobals() as $key => $value) {
1078
+ if (!array_key_exists($key, $context)) {
1079
+ $context[$key] = $value;
1080
+ }
1081
+ }
1082
+
1083
+ return $context;
1084
+ }
1085
+
1086
+ /**
1087
+ * Gets the registered unary Operators.
1088
+ *
1089
+ * @return array An array of unary operators
1090
+ */
1091
+ public function getUnaryOperators()
1092
+ {
1093
+ if (!$this->extensionInitialized) {
1094
+ $this->initExtensions();
1095
+ }
1096
+
1097
+ return $this->unaryOperators;
1098
+ }
1099
+
1100
+ /**
1101
+ * Gets the registered binary Operators.
1102
+ *
1103
+ * @return array An array of binary operators
1104
+ */
1105
+ public function getBinaryOperators()
1106
+ {
1107
+ if (!$this->extensionInitialized) {
1108
+ $this->initExtensions();
1109
+ }
1110
+
1111
+ return $this->binaryOperators;
1112
+ }
1113
+
1114
+ public function computeAlternatives($name, $items)
1115
+ {
1116
+ $alternatives = array();
1117
+ foreach ($items as $item) {
1118
+ $lev = levenshtein($name, $item);
1119
+ if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
1120
+ $alternatives[$item] = $lev;
1121
+ }
1122
+ }
1123
+ asort($alternatives);
1124
+
1125
+ return array_keys($alternatives);
1126
+ }
1127
+
1128
+ protected function initGlobals()
1129
+ {
1130
+ $globals = array();
1131
+ foreach ($this->extensions as $extension) {
1132
+ $extGlob = $extension->getGlobals();
1133
+ if (!is_array($extGlob)) {
1134
+ throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
1135
+ }
1136
+
1137
+ $globals[] = $extGlob;
1138
+ }
1139
+
1140
+ $globals[] = $this->staging->getGlobals();
1141
+
1142
+ return call_user_func_array('array_merge', $globals);
1143
+ }
1144
+
1145
+ protected function initExtensions()
1146
+ {
1147
+ if ($this->extensionInitialized) {
1148
+ return;
1149
+ }
1150
+
1151
+ $this->extensionInitialized = true;
1152
+ $this->parsers = new Twig_TokenParserBroker();
1153
+ $this->filters = array();
1154
+ $this->functions = array();
1155
+ $this->tests = array();
1156
+ $this->visitors = array();
1157
+ $this->unaryOperators = array();
1158
+ $this->binaryOperators = array();
1159
+
1160
+ foreach ($this->extensions as $extension) {
1161
+ $this->initExtension($extension);
1162
+ }
1163
+ $this->initExtension($this->staging);
1164
+ }
1165
+
1166
+ protected function initExtension(Twig_ExtensionInterface $extension)
1167
+ {
1168
+ // filters
1169
+ foreach ($extension->getFilters() as $name => $filter) {
1170
+ if ($name instanceof Twig_SimpleFilter) {
1171
+ $filter = $name;
1172
+ $name = $filter->getName();
1173
+ } elseif ($filter instanceof Twig_SimpleFilter) {
1174
+ $name = $filter->getName();
1175
+ }
1176
+
1177
+ $this->filters[$name] = $filter;
1178
+ }
1179
+
1180
+ // functions
1181
+ foreach ($extension->getFunctions() as $name => $function) {
1182
+ if ($name instanceof Twig_SimpleFunction) {
1183
+ $function = $name;
1184
+ $name = $function->getName();
1185
+ } elseif ($function instanceof Twig_SimpleFunction) {
1186
+ $name = $function->getName();
1187
+ }
1188
+
1189
+ $this->functions[$name] = $function;
1190
+ }
1191
+
1192
+ // tests
1193
+ foreach ($extension->getTests() as $name => $test) {
1194
+ if ($name instanceof Twig_SimpleTest) {
1195
+ $test = $name;
1196
+ $name = $test->getName();
1197
+ } elseif ($test instanceof Twig_SimpleTest) {
1198
+ $name = $test->getName();
1199
+ }
1200
+
1201
+ $this->tests[$name] = $test;
1202
+ }
1203
+
1204
+ // token parsers
1205
+ foreach ($extension->getTokenParsers() as $parser) {
1206
+ if ($parser instanceof Twig_TokenParserInterface) {
1207
+ $this->parsers->addTokenParser($parser);
1208
+ } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
1209
+ $this->parsers->addTokenParserBroker($parser);
1210
+ } else {
1211
+ throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
1212
+ }
1213
+ }
1214
+
1215
+ // node visitors
1216
+ foreach ($extension->getNodeVisitors() as $visitor) {
1217
+ $this->visitors[] = $visitor;
1218
+ }
1219
+
1220
+ // operators
1221
+ if ($operators = $extension->getOperators()) {
1222
+ if (2 !== count($operators)) {
1223
+ throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
1224
+ }
1225
+
1226
+ $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
1227
+ $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
1228
+ }
1229
+ }
1230
+
1231
+ protected function writeCacheFile($file, $content)
1232
+ {
1233
+ $dir = dirname($file);
1234
+ if (!is_dir($dir)) {
1235
+ if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
1236
+ throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir));
1237
+ }
1238
+ } elseif (!is_writable($dir)) {
1239
+ throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
1240
+ }
1241
+
1242
+ $tmpFile = tempnam($dir, basename($file));
1243
+ if (false !== @file_put_contents($tmpFile, $content)) {
1244
+ // rename does not work on Win32 before 5.2.6
1245
+ if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
1246
+ @chmod($file, 0666 & ~umask());
1247
+
1248
+ return;
1249
+ }
1250
+ }
1251
+
1252
+ throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
1253
+ }
1254
+ }
classes/Twig/Error.php ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig base exception.
14
+ *
15
+ * This exception class and its children must only be used when
16
+ * an error occurs during the loading of a template, when a syntax error
17
+ * is detected in a template, or when rendering a template. Other
18
+ * errors must use regular PHP exception classes (like when the template
19
+ * cache directory is not writable for instance).
20
+ *
21
+ * To help debugging template issues, this class tracks the original template
22
+ * name and line where the error occurred.
23
+ *
24
+ * Whenever possible, you must set these information (original template name
25
+ * and line number) yourself by passing them to the constructor. If some or all
26
+ * these information are not available from where you throw the exception, then
27
+ * this class will guess them automatically (when the line number is set to -1
28
+ * and/or the filename is set to null). As this is a costly operation, this
29
+ * can be disabled by passing false for both the filename and the line number
30
+ * when creating a new instance of this class.
31
+ *
32
+ * @author Fabien Potencier <fabien@symfony.com>
33
+ */
34
+ class Twig_Error extends Exception
35
+ {
36
+ protected $lineno;
37
+ protected $filename;
38
+ protected $rawMessage;
39
+ protected $previous;
40
+
41
+ /**
42
+ * Constructor.
43
+ *
44
+ * Set both the line number and the filename to false to
45
+ * disable automatic guessing of the original template name
46
+ * and line number.
47
+ *
48
+ * Set the line number to -1 to enable its automatic guessing.
49
+ * Set the filename to null to enable its automatic guessing.
50
+ *
51
+ * By default, automatic guessing is enabled.
52
+ *
53
+ * @param string $message The error message
54
+ * @param int $lineno The template line where the error occurred
55
+ * @param string $filename The template file name where the error occurred
56
+ * @param Exception $previous The previous exception
57
+ */
58
+ public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
59
+ {
60
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
61
+ $this->previous = $previous;
62
+ parent::__construct('');
63
+ } else {
64
+ parent::__construct('', 0, $previous);
65
+ }
66
+
67
+ $this->lineno = $lineno;
68
+ $this->filename = $filename;
69
+
70
+ if (-1 === $this->lineno || null === $this->filename) {
71
+ $this->guessTemplateInfo();
72
+ }
73
+
74
+ $this->rawMessage = $message;
75
+
76
+ $this->updateRepr();
77
+ }
78
+
79
+ /**
80
+ * Gets the raw message.
81
+ *
82
+ * @return string The raw message
83
+ */
84
+ public function getRawMessage()
85
+ {
86
+ return $this->rawMessage;
87
+ }
88
+
89
+ /**
90
+ * Gets the filename where the error occurred.
91
+ *
92
+ * @return string The filename
93
+ */
94
+ public function getTemplateFile()
95
+ {
96
+ return $this->filename;
97
+ }
98
+
99
+ /**
100
+ * Sets the filename where the error occurred.
101
+ *
102
+ * @param string $filename The filename
103
+ */
104
+ public function setTemplateFile($filename)
105
+ {
106
+ $this->filename = $filename;
107
+
108
+ $this->updateRepr();
109
+ }
110
+
111
+ /**
112
+ * Gets the template line where the error occurred.
113
+ *
114
+ * @return int The template line
115
+ */
116
+ public function getTemplateLine()
117
+ {
118
+ return $this->lineno;
119
+ }
120
+
121
+ /**
122
+ * Sets the template line where the error occurred.
123
+ *
124
+ * @param int $lineno The template line
125
+ */
126
+ public function setTemplateLine($lineno)
127
+ {
128
+ $this->lineno = $lineno;
129
+
130
+ $this->updateRepr();
131
+ }
132
+
133
+ public function guess()
134
+ {
135
+ $this->guessTemplateInfo();
136
+ $this->updateRepr();
137
+ }
138
+
139
+ /**
140
+ * For PHP < 5.3.0, provides access to the getPrevious() method.
141
+ *
142
+ * @param string $method The method name
143
+ * @param array $arguments The parameters to be passed to the method
144
+ *
145
+ * @return Exception The previous exception or null
146
+ *
147
+ * @throws BadMethodCallException
148
+ */
149
+ public function __call($method, $arguments)
150
+ {
151
+ if ('getprevious' == strtolower($method)) {
152
+ return $this->previous;
153
+ }
154
+
155
+ throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
156
+ }
157
+
158
+ protected function updateRepr()
159
+ {
160
+ $this->message = $this->rawMessage;
161
+
162
+ $dot = false;
163
+ if ('.' === substr($this->message, -1)) {
164
+ $this->message = substr($this->message, 0, -1);
165
+ $dot = true;
166
+ }
167
+
168
+ if ($this->filename) {
169
+ if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
170
+ $filename = sprintf('"%s"', $this->filename);
171
+ } else {
172
+ $filename = json_encode($this->filename);
173
+ }
174
+ $this->message .= sprintf(' in %s', $filename);
175
+ }
176
+
177
+ if ($this->lineno && $this->lineno >= 0) {
178
+ $this->message .= sprintf(' at line %d', $this->lineno);
179
+ }
180
+
181
+ if ($dot) {
182
+ $this->message .= '.';
183
+ }
184
+ }
185
+
186
+ protected function guessTemplateInfo()
187
+ {
188
+ $template = null;
189
+ $templateClass = null;
190
+
191
+ if (version_compare(phpversion(), '5.3.6', '>=')) {
192
+ $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
193
+ } else {
194
+ $backtrace = debug_backtrace();
195
+ }
196
+
197
+ foreach ($backtrace as $trace) {
198
+ if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
199
+ $currentClass = get_class($trace['object']);
200
+ $isEmbedContainer = 0 === strpos($templateClass, $currentClass);
201
+ if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
202
+ $template = $trace['object'];
203
+ $templateClass = get_class($trace['object']);
204
+ }
205
+ }
206
+ }
207
+
208
+ // update template filename
209
+ if (null !== $template && null === $this->filename) {
210
+ $this->filename = $template->getTemplateName();
211
+ }
212
+
213
+ if (null === $template || $this->lineno > -1) {
214
+ return;
215
+ }
216
+
217
+ $r = new ReflectionObject($template);
218
+ $file = $r->getFileName();
219
+
220
+ // hhvm has a bug where eval'ed files comes out as the current directory
221
+ if (is_dir($file)) {
222
+ $file = '';
223
+ }
224
+
225
+ $exceptions = array($e = $this);
226
+ while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
227
+ $exceptions[] = $e;
228
+ }
229
+
230
+ while ($e = array_pop($exceptions)) {
231
+ $traces = $e->getTrace();
232
+ while ($trace = array_shift($traces)) {
233
+ if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
234
+ continue;
235
+ }
236
+
237
+ foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
238
+ if ($codeLine <= $trace['line']) {
239
+ // update template line
240
+ $this->lineno = $templateLine;
241
+
242
+ return;
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
classes/Twig/Error/Loader.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Exception thrown when an error occurs during template loading.
14
+ *
15
+ * Automatic template information guessing is always turned off as
16
+ * if a template cannot be loaded, there is nothing to guess.
17
+ * However, when a template is loaded from another one, then, we need
18
+ * to find the current context and this is automatically done by
19
+ * Twig_Template::displayWithErrorHandling().
20
+ *
21
+ * This strategy makes Twig_Environment::resolveTemplate() much faster.
22
+ *
23
+ * @author Fabien Potencier <fabien@symfony.com>
24
+ */
25
+ class Twig_Error_Loader extends Twig_Error
26
+ {
27
+ public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
28
+ {
29
+ parent::__construct($message, false, false, $previous);
30
+ }
31
+ }
classes/Twig/Error/Runtime.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Exception thrown when an error occurs at runtime.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Error_Runtime extends Twig_Error
19
+ {
20
+ }
classes/Twig/Error/Syntax.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Exception thrown when a syntax error occurs during lexing or parsing of a template.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Error_Syntax extends Twig_Error
19
+ {
20
+ }
classes/Twig/ExistsLoaderInterface.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Adds an exists() method for loaders.
14
+ *
15
+ * @author Florin Patan <florinpatan@gmail.com>
16
+ *
17
+ * @deprecated since 1.12 (to be removed in 3.0)
18
+ */
19
+ interface Twig_ExistsLoaderInterface
20
+ {
21
+ /**
22
+ * Check if we have the source code of a template, given its name.
23
+ *
24
+ * @param string $name The name of the template to check if we can load
25
+ *
26
+ * @return bool If the template source code is handled by this loader or not
27
+ */
28
+ public function exists($name);
29
+ }
classes/Twig/ExpressionParser.php ADDED
@@ -0,0 +1,598 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Parses expressions.
15
+ *
16
+ * This parser implements a "Precedence climbing" algorithm.
17
+ *
18
+ * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
19
+ * @see http://en.wikipedia.org/wiki/Operator-precedence_parser
20
+ *
21
+ * @author Fabien Potencier <fabien@symfony.com>
22
+ */
23
+ class Twig_ExpressionParser
24
+ {
25
+ const OPERATOR_LEFT = 1;
26
+ const OPERATOR_RIGHT = 2;
27
+
28
+ protected $parser;
29
+ protected $unaryOperators;
30
+ protected $binaryOperators;
31
+
32
+ public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
33
+ {
34
+ $this->parser = $parser;
35
+ $this->unaryOperators = $unaryOperators;
36
+ $this->binaryOperators = $binaryOperators;
37
+ }
38
+
39
+ public function parseExpression($precedence = 0)
40
+ {
41
+ $expr = $this->getPrimary();
42
+ $token = $this->parser->getCurrentToken();
43
+ while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
44
+ $op = $this->binaryOperators[$token->getValue()];
45
+ $this->parser->getStream()->next();
46
+
47
+ if (isset($op['callable'])) {
48
+ $expr = call_user_func($op['callable'], $this->parser, $expr);
49
+ } else {
50
+ $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
51
+ $class = $op['class'];
52
+ $expr = new $class($expr, $expr1, $token->getLine());
53
+ }
54
+
55
+ $token = $this->parser->getCurrentToken();
56
+ }
57
+
58
+ if (0 === $precedence) {
59
+ return $this->parseConditionalExpression($expr);
60
+ }
61
+
62
+ return $expr;
63
+ }
64
+
65
+ protected function getPrimary()
66
+ {
67
+ $token = $this->parser->getCurrentToken();
68
+
69
+ if ($this->isUnary($token)) {
70
+ $operator = $this->unaryOperators[$token->getValue()];
71
+ $this->parser->getStream()->next();
72
+ $expr = $this->parseExpression($operator['precedence']);
73
+ $class = $operator['class'];
74
+
75
+ return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
76
+ } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
77
+ $this->parser->getStream()->next();
78
+ $expr = $this->parseExpression();
79
+ $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
80
+
81
+ return $this->parsePostfixExpression($expr);
82
+ }
83
+
84
+ return $this->parsePrimaryExpression();
85
+ }
86
+
87
+ protected function parseConditionalExpression($expr)
88
+ {
89
+ while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) {
90
+ if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
91
+ $expr2 = $this->parseExpression();
92
+ if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
93
+ $expr3 = $this->parseExpression();
94
+ } else {
95
+ $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
96
+ }
97
+ } else {
98
+ $expr2 = $expr;
99
+ $expr3 = $this->parseExpression();
100
+ }
101
+
102
+ $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
103
+ }
104
+
105
+ return $expr;
106
+ }
107
+
108
+ protected function isUnary(Twig_Token $token)
109
+ {
110
+ return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
111
+ }
112
+
113
+ protected function isBinary(Twig_Token $token)
114
+ {
115
+ return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
116
+ }
117
+
118
+ public function parsePrimaryExpression()
119
+ {
120
+ $token = $this->parser->getCurrentToken();
121
+ switch ($token->getType()) {
122
+ case Twig_Token::NAME_TYPE:
123
+ $this->parser->getStream()->next();
124
+ switch ($token->getValue()) {
125
+ case 'true':
126
+ case 'TRUE':
127
+ $node = new Twig_Node_Expression_Constant(true, $token->getLine());
128
+ break;
129
+
130
+ case 'false':
131
+ case 'FALSE':
132
+ $node = new Twig_Node_Expression_Constant(false, $token->getLine());
133
+ break;
134
+
135
+ case 'none':
136
+ case 'NONE':
137
+ case 'null':
138
+ case 'NULL':
139
+ $node = new Twig_Node_Expression_Constant(null, $token->getLine());
140
+ break;
141
+
142
+ default:
143
+ if ('(' === $this->parser->getCurrentToken()->getValue()) {
144
+ $node = $this->getFunctionNode($token->getValue(), $token->getLine());
145
+ } else {
146
+ $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
147
+ }
148
+ }
149
+ break;
150
+
151
+ case Twig_Token::NUMBER_TYPE:
152
+ $this->parser->getStream()->next();
153
+ $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
154
+ break;
155
+
156
+ case Twig_Token::STRING_TYPE:
157
+ case Twig_Token::INTERPOLATION_START_TYPE:
158
+ $node = $this->parseStringExpression();
159
+ break;
160
+
161
+ case Twig_Token::OPERATOR_TYPE:
162
+ if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
163
+ // in this context, string operators are variable names
164
+ $this->parser->getStream()->next();
165
+ $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
166
+ break;
167
+ }
168
+
169
+ default:
170
+ if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
171
+ $node = $this->parseArrayExpression();
172
+ } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
173
+ $node = $this->parseHashExpression();
174
+ } else {
175
+ throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getFilename());
176
+ }
177
+ }
178
+
179
+ return $this->parsePostfixExpression($node);
180
+ }
181
+
182
+ public function parseStringExpression()
183
+ {
184
+ $stream = $this->parser->getStream();
185
+
186
+ $nodes = array();
187
+ // a string cannot be followed by another string in a single expression
188
+ $nextCanBeString = true;
189
+ while (true) {
190
+ if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) {
191
+ $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
192
+ $nextCanBeString = false;
193
+ } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) {
194
+ $nodes[] = $this->parseExpression();
195
+ $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
196
+ $nextCanBeString = true;
197
+ } else {
198
+ break;
199
+ }
200
+ }
201
+
202
+ $expr = array_shift($nodes);
203
+ foreach ($nodes as $node) {
204
+ $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine());
205
+ }
206
+
207
+ return $expr;
208
+ }
209
+
210
+ public function parseArrayExpression()
211
+ {
212
+ $stream = $this->parser->getStream();
213
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
214
+
215
+ $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
216
+ $first = true;
217
+ while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
218
+ if (!$first) {
219
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
220
+
221
+ // trailing ,?
222
+ if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
223
+ break;
224
+ }
225
+ }
226
+ $first = false;
227
+
228
+ $node->addElement($this->parseExpression());
229
+ }
230
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
231
+
232
+ return $node;
233
+ }
234
+
235
+ public function parseHashExpression()
236
+ {
237
+ $stream = $this->parser->getStream();
238
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
239
+
240
+ $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
241
+ $first = true;
242
+ while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
243
+ if (!$first) {
244
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
245
+
246
+ // trailing ,?
247
+ if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
248
+ break;
249
+ }
250
+ }
251
+ $first = false;
252
+
253
+ // a hash key can be:
254
+ //
255
+ // * a number -- 12
256
+ // * a string -- 'a'
257
+ // * a name, which is equivalent to a string -- a
258
+ // * an expression, which must be enclosed in parentheses -- (1 + 2)
259
+ if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) {
260
+ $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
261
+ } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
262
+ $key = $this->parseExpression();
263
+ } else {
264
+ $current = $stream->getCurrent();
265
+
266
+ throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $this->parser->getFilename());
267
+ }
268
+
269
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
270
+ $value = $this->parseExpression();
271
+
272
+ $node->addElement($value, $key);
273
+ }
274
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
275
+
276
+ return $node;
277
+ }
278
+
279
+ public function parsePostfixExpression($node)
280
+ {
281
+ while (true) {
282
+ $token = $this->parser->getCurrentToken();
283
+ if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
284
+ if ('.' == $token->getValue() || '[' == $token->getValue()) {
285
+ $node = $this->parseSubscriptExpression($node);
286
+ } elseif ('|' == $token->getValue()) {
287
+ $node = $this->parseFilterExpression($node);
288
+ } else {
289
+ break;
290
+ }
291
+ } else {
292
+ break;
293
+ }
294
+ }
295
+
296
+ return $node;
297
+ }
298
+
299
+ public function getFunctionNode($name, $line)
300
+ {
301
+ switch ($name) {
302
+ case 'parent':
303
+ $args = $this->parseArguments();
304
+ if (!count($this->parser->getBlockStack())) {
305
+ throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
306
+ }
307
+
308
+ if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
309
+ throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename());
310
+ }
311
+
312
+ return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
313
+ case 'block':
314
+ return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line);
315
+ case 'attribute':
316
+ $args = $this->parseArguments();
317
+ if (count($args) < 2) {
318
+ throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
319
+ }
320
+
321
+ return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line);
322
+ default:
323
+ if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
324
+ $arguments = new Twig_Node_Expression_Array(array(), $line);
325
+ foreach ($this->parseArguments() as $n) {
326
+ $arguments->addElement($n);
327
+ }
328
+
329
+ $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
330
+ $node->setAttribute('safe', true);
331
+
332
+ return $node;
333
+ }
334
+
335
+ $args = $this->parseArguments(true);
336
+ $class = $this->getFunctionNodeClass($name, $line);
337
+
338
+ return new $class($name, $args, $line);
339
+ }
340
+ }
341
+
342
+ public function parseSubscriptExpression($node)
343
+ {
344
+ $stream = $this->parser->getStream();
345
+ $token = $stream->next();
346
+ $lineno = $token->getLine();
347
+ $arguments = new Twig_Node_Expression_Array(array(), $lineno);
348
+ $type = Twig_Template::ANY_CALL;
349
+ if ($token->getValue() == '.') {
350
+ $token = $stream->next();
351
+ if (
352
+ $token->getType() == Twig_Token::NAME_TYPE
353
+ ||
354
+ $token->getType() == Twig_Token::NUMBER_TYPE
355
+ ||
356
+ ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
357
+ ) {
358
+ $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
359
+
360
+ if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
361
+ $type = Twig_TemplateInterface::METHOD_CALL;
362
+ foreach ($this->parseArguments() as $n) {
363
+ $arguments->addElement($n);
364
+ }
365
+ }
366
+ } else {
367
+ throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
368
+ }
369
+
370
+ if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
371
+ if (!$arg instanceof Twig_Node_Expression_Constant) {
372
+ throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
373
+ }
374
+
375
+ $node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
376
+ $node->setAttribute('safe', true);
377
+
378
+ return $node;
379
+ }
380
+ } else {
381
+ $type = Twig_Template::ARRAY_CALL;
382
+
383
+ // slice?
384
+ $slice = false;
385
+ if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
386
+ $slice = true;
387
+ $arg = new Twig_Node_Expression_Constant(0, $token->getLine());
388
+ } else {
389
+ $arg = $this->parseExpression();
390
+ }
391
+
392
+ if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
393
+ $slice = true;
394
+ }
395
+
396
+ if ($slice) {
397
+ if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
398
+ $length = new Twig_Node_Expression_Constant(null, $token->getLine());
399
+ } else {
400
+ $length = $this->parseExpression();
401
+ }
402
+
403
+ $class = $this->getFilterNodeClass('slice', $token->getLine());
404
+ $arguments = new Twig_Node(array($arg, $length));
405
+ $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
406
+
407
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
408
+
409
+ return $filter;
410
+ }
411
+
412
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
413
+ }
414
+
415
+ return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
416
+ }
417
+
418
+ public function parseFilterExpression($node)
419
+ {
420
+ $this->parser->getStream()->next();
421
+
422
+ return $this->parseFilterExpressionRaw($node);
423
+ }
424
+
425
+ public function parseFilterExpressionRaw($node, $tag = null)
426
+ {
427
+ while (true) {
428
+ $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE);
429
+
430
+ $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
431
+ if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
432
+ $arguments = new Twig_Node();
433
+ } else {
434
+ $arguments = $this->parseArguments(true);
435
+ }
436
+
437
+ $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());
438
+
439
+ $node = new $class($node, $name, $arguments, $token->getLine(), $tag);
440
+
441
+ if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
442
+ break;
443
+ }
444
+
445
+ $this->parser->getStream()->next();
446
+ }
447
+
448
+ return $node;
449
+ }
450
+
451
+ /**
452
+ * Parses arguments.
453
+ *
454
+ * @param bool $namedArguments Whether to allow named arguments or not
455
+ * @param bool $definition Whether we are parsing arguments for a function definition
456
+ */
457
+ public function parseArguments($namedArguments = false, $definition = false)
458
+ {
459
+ $args = array();
460
+ $stream = $this->parser->getStream();
461
+
462
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
463
+ while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
464
+ if (!empty($args)) {
465
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
466
+ }
467
+
468
+ if ($definition) {
469
+ $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name');
470
+ $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine());
471
+ } else {
472
+ $value = $this->parseExpression();
473
+ }
474
+
475
+ $name = null;
476
+ if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
477
+ if (!$value instanceof Twig_Node_Expression_Name) {
478
+ throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
479
+ }
480
+ $name = $value->getAttribute('name');
481
+
482
+ if ($definition) {
483
+ $value = $this->parsePrimaryExpression();
484
+
485
+ if (!$this->checkConstantExpression($value)) {
486
+ throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename());
487
+ }
488
+ } else {
489
+ $value = $this->parseExpression();
490
+ }
491
+ }
492
+
493
+ if ($definition) {
494
+ if (null === $name) {
495
+ $name = $value->getAttribute('name');
496
+ $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
497
+ }
498
+ $args[$name] = $value;
499
+ } else {
500
+ if (null === $name) {
501
+ $args[] = $value;
502
+ } else {
503
+ $args[$name] = $value;
504
+ }
505
+ }
506
+ }
507
+ $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
508
+
509
+ return new Twig_Node($args);
510
+ }
511
+
512
+ public function parseAssignmentExpression()
513
+ {
514
+ $targets = array();
515
+ while (true) {
516
+ $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
517
+ if (in_array($token->getValue(), array('true', 'false', 'none'))) {
518
+ throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
519
+ }
520
+ $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
521
+
522
+ if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
523
+ break;
524
+ }
525
+ }
526
+
527
+ return new Twig_Node($targets);
528
+ }
529
+
530
+ public function parseMultitargetExpression()
531
+ {
532
+ $targets = array();
533
+ while (true) {
534
+ $targets[] = $this->parseExpression();
535
+ if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
536
+ break;
537
+ }
538
+ }
539
+
540
+ return new Twig_Node($targets);
541
+ }
542
+
543
+ protected function getFunctionNodeClass($name, $line)
544
+ {
545
+ $env = $this->parser->getEnvironment();
546
+
547
+ if (false === $function = $env->getFunction($name)) {
548
+ $message = sprintf('The function "%s" does not exist', $name);
549
+ if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) {
550
+ $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
551
+ }
552
+
553
+ throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
554
+ }
555
+
556
+ if ($function instanceof Twig_SimpleFunction) {
557
+ return $function->getNodeClass();
558
+ }
559
+
560
+ return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function';
561
+ }
562
+
563
+ protected function getFilterNodeClass($name, $line)
564
+ {
565
+ $env = $this->parser->getEnvironment();
566
+
567
+ if (false === $filter = $env->getFilter($name)) {
568
+ $message = sprintf('The filter "%s" does not exist', $name);
569
+ if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) {
570
+ $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
571
+ }
572
+
573
+ throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
574
+ }
575
+
576
+ if ($filter instanceof Twig_SimpleFilter) {
577
+ return $filter->getNodeClass();
578
+ }
579
+
580
+ return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter';
581
+ }
582
+
583
+ // checks that the node only contains "constant" elements
584
+ protected function checkConstantExpression(Twig_NodeInterface $node)
585
+ {
586
+ if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
587
+ return false;
588
+ }
589
+
590
+ foreach ($node as $n) {
591
+ if (!$this->checkConstantExpression($n)) {
592
+ return false;
593
+ }
594
+ }
595
+
596
+ return true;
597
+ }
598
+ }
classes/Twig/Extension.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ abstract class Twig_Extension implements Twig_ExtensionInterface
12
+ {
13
+ /**
14
+ * Initializes the runtime environment.
15
+ *
16
+ * This is where you can load some file that contains filter functions for instance.
17
+ *
18
+ * @param Twig_Environment $environment The current Twig_Environment instance
19
+ */
20
+ public function initRuntime(Twig_Environment $environment)
21
+ {
22
+ }
23
+
24
+ /**
25
+ * Returns the token parser instances to add to the existing list.
26
+ *
27
+ * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
28
+ */
29
+ public function getTokenParsers()
30
+ {
31
+ return array();
32
+ }
33
+
34
+ /**
35
+ * Returns the node visitor instances to add to the existing list.
36
+ *
37
+ * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
38
+ */
39
+ public function getNodeVisitors()
40
+ {
41
+ return array();
42
+ }
43
+
44
+ /**
45
+ * Returns a list of filters to add to the existing list.
46
+ *
47
+ * @return array An array of filters
48
+ */
49
+ public function getFilters()
50
+ {
51
+ return array();
52
+ }
53
+
54
+ /**
55
+ * Returns a list of tests to add to the existing list.
56
+ *
57
+ * @return array An array of tests
58
+ */
59
+ public function getTests()
60
+ {
61
+ return array();
62
+ }
63
+
64
+ /**
65
+ * Returns a list of functions to add to the existing list.
66
+ *
67
+ * @return array An array of functions
68
+ */
69
+ public function getFunctions()
70
+ {
71
+ return array();
72
+ }
73
+
74
+ /**
75
+ * Returns a list of operators to add to the existing list.
76
+ *
77
+ * @return array An array of operators
78
+ */
79
+ public function getOperators()
80
+ {
81
+ return array();
82
+ }
83
+
84
+ /**
85
+ * Returns a list of global variables to add to the existing list.
86
+ *
87
+ * @return array An array of global variables
88
+ */
89
+ public function getGlobals()
90
+ {
91
+ return array();
92
+ }
93
+ }
classes/Twig/Extension/Core.php ADDED
@@ -0,0 +1,1462 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined('ENT_SUBSTITUTE')) {
4
+ // use 0 as hhvm does not support several flags yet
5
+ define('ENT_SUBSTITUTE', 0);
6
+ }
7
+
8
+ /*
9
+ * This file is part of Twig.
10
+ *
11
+ * (c) 2009 Fabien Potencier
12
+ *
13
+ * For the full copyright and license information, please view the LICENSE
14
+ * file that was distributed with this source code.
15
+ */
16
+ class Twig_Extension_Core extends Twig_Extension
17
+ {
18
+ protected $dateFormats = array('F j, Y H:i', '%d days');
19
+ protected $numberFormat = array(0, '.', ',');
20
+ protected $timezone = null;
21
+ protected $escapers = array();
22
+
23
+ /**
24
+ * Defines a new escaper to be used via the escape filter.
25
+ *
26
+ * @param string $strategy The strategy name that should be used as a strategy in the escape call
27
+ * @param callable $callable A valid PHP callable
28
+ */
29
+ public function setEscaper($strategy, $callable)
30
+ {
31
+ $this->escapers[$strategy] = $callable;
32
+ }
33
+
34
+ /**
35
+ * Gets all defined escapers.
36
+ *
37
+ * @return array An array of escapers
38
+ */
39
+ public function getEscapers()
40
+ {
41
+ return $this->escapers;
42
+ }
43
+
44
+ /**
45
+ * Sets the default format to be used by the date filter.
46
+ *
47
+ * @param string $format The default date format string
48
+ * @param string $dateIntervalFormat The default date interval format string
49
+ */
50
+ public function setDateFormat($format = null, $dateIntervalFormat = null)
51
+ {
52
+ if (null !== $format) {
53
+ $this->dateFormats[0] = $format;
54
+ }
55
+
56
+ if (null !== $dateIntervalFormat) {
57
+ $this->dateFormats[1] = $dateIntervalFormat;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Gets the default format to be used by the date filter.
63
+ *
64
+ * @return array The default date format string and the default date interval format string
65
+ */
66
+ public function getDateFormat()
67
+ {
68
+ return $this->dateFormats;
69
+ }
70
+
71
+ /**
72
+ * Sets the default timezone to be used by the date filter.
73
+ *
74
+ * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
75
+ */
76
+ public function setTimezone($timezone)
77
+ {
78
+ $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
79
+ }
80
+
81
+ /**
82
+ * Gets the default timezone to be used by the date filter.
83
+ *
84
+ * @return DateTimeZone The default timezone currently in use
85
+ */
86
+ public function getTimezone()
87
+ {
88
+ if (null === $this->timezone) {
89
+ $this->timezone = new DateTimeZone(date_default_timezone_get());
90
+ }
91
+
92
+ return $this->timezone;
93
+ }
94
+
95
+ /**
96
+ * Sets the default format to be used by the number_format filter.
97
+ *
98
+ * @param int $decimal The number of decimal places to use.
99
+ * @param string $decimalPoint The character(s) to use for the decimal point.
100
+ * @param string $thousandSep The character(s) to use for the thousands separator.
101
+ */
102
+ public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
103
+ {
104
+ $this->numberFormat = array($decimal, $decimalPoint, $thousandSep);
105
+ }
106
+
107
+ /**
108
+ * Get the default format used by the number_format filter.
109
+ *
110
+ * @return array The arguments for number_format()
111
+ */
112
+ public function getNumberFormat()
113
+ {
114
+ return $this->numberFormat;
115
+ }
116
+
117
+ /**
118
+ * Returns the token parser instance to add to the existing list.
119
+ *
120
+ * @return Twig_TokenParser[] An array of Twig_TokenParser instances
121
+ */
122
+ public function getTokenParsers()
123
+ {
124
+ return array(
125
+ new Twig_TokenParser_For(),
126
+ new Twig_TokenParser_If(),
127
+ new Twig_TokenParser_Extends(),
128
+ new Twig_TokenParser_Include(),
129
+ new Twig_TokenParser_Block(),
130
+ new Twig_TokenParser_Use(),
131
+ new Twig_TokenParser_Filter(),
132
+ new Twig_TokenParser_Macro(),
133
+ new Twig_TokenParser_Import(),
134
+ new Twig_TokenParser_From(),
135
+ new Twig_TokenParser_Set(),
136
+ new Twig_TokenParser_Spaceless(),
137
+ new Twig_TokenParser_Flush(),
138
+ new Twig_TokenParser_Do(),
139
+ new Twig_TokenParser_Embed(),
140
+ );
141
+ }
142
+
143
+ /**
144
+ * Returns a list of filters to add to the existing list.
145
+ *
146
+ * @return array An array of filters
147
+ */
148
+ public function getFilters()
149
+ {
150
+ $filters = array(
151
+ // formatting filters
152
+ new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)),
153
+ new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
154
+ new Twig_SimpleFilter('format', 'sprintf'),
155
+ new Twig_SimpleFilter('replace', 'strtr'),
156
+ new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
157
+ new Twig_SimpleFilter('abs', 'abs'),
158
+ new Twig_SimpleFilter('round', 'twig_round'),
159
+
160
+ // encoding
161
+ new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
162
+ new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'),
163
+ new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'),
164
+
165
+ // string filters
166
+ new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)),
167
+ new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)),
168
+ new Twig_SimpleFilter('upper', 'strtoupper'),
169
+ new Twig_SimpleFilter('lower', 'strtolower'),
170
+ new Twig_SimpleFilter('striptags', 'strip_tags'),
171
+ new Twig_SimpleFilter('trim', 'trim'),
172
+ new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
173
+
174
+ // array helpers
175
+ new Twig_SimpleFilter('join', 'twig_join_filter'),
176
+ new Twig_SimpleFilter('split', 'twig_split_filter'),
177
+ new Twig_SimpleFilter('sort', 'twig_sort_filter'),
178
+ new Twig_SimpleFilter('merge', 'twig_array_merge'),
179
+ new Twig_SimpleFilter('batch', 'twig_array_batch'),
180
+
181
+ // string/array filters
182
+ new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
183
+ new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
184
+ new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
185
+ new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)),
186
+ new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)),
187
+
188
+ // iteration and runtime
189
+ new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
190
+ new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'),
191
+
192
+ // escaping
193
+ new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
194
+ new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
195
+ );
196
+
197
+ if (function_exists('mb_get_info')) {
198
+ $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true));
199
+ $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true));
200
+ }
201
+
202
+ return $filters;
203
+ }
204
+
205
+ /**
206
+ * Returns a list of global functions to add to the existing list.
207
+ *
208
+ * @return array An array of global functions
209
+ */
210
+ public function getFunctions()
211
+ {
212
+ return array(
213
+ new Twig_SimpleFunction('max', 'max'),
214
+ new Twig_SimpleFunction('min', 'min'),
215
+ new Twig_SimpleFunction('range', 'range'),
216
+ new Twig_SimpleFunction('constant', 'twig_constant'),
217
+ new Twig_SimpleFunction('cycle', 'twig_cycle'),
218
+ new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
219
+ new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
220
+ new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))),
221
+ new Twig_SimpleFunction('source', 'twig_source', array('needs_environment' => true, 'is_safe' => array('all'))),
222
+ );
223
+ }
224
+
225
+ /**
226
+ * Returns a list of tests to add to the existing list.
227
+ *
228
+ * @return array An array of tests
229
+ */
230
+ public function getTests()
231
+ {
232
+ return array(
233
+ new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
234
+ new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
235
+ new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
236
+ new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
237
+ new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
238
+ new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
239
+ new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
240
+ new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
241
+ new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
242
+ new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
243
+ new Twig_SimpleTest('empty', 'twig_test_empty'),
244
+ new Twig_SimpleTest('iterable', 'twig_test_iterable'),
245
+ );
246
+ }
247
+
248
+ /**
249
+ * Returns a list of operators to add to the existing list.
250
+ *
251
+ * @return array An array of operators
252
+ */
253
+ public function getOperators()
254
+ {
255
+ return array(
256
+ array(
257
+ 'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
258
+ '-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
259
+ '+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
260
+ ),
261
+ array(
262
+ 'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
263
+ 'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
264
+ 'b-or' => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
265
+ 'b-xor' => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
266
+ 'b-and' => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
267
+ '==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
268
+ '!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
269
+ '<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
270
+ '>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
271
+ '>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
272
+ '<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
273
+ 'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
274
+ 'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
275
+ 'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
276
+ 'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
277
+ 'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
278
+ '..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
279
+ '+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
280
+ '-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
281
+ '~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
282
+ '*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
283
+ '/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
284
+ '//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
285
+ '%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
286
+ 'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
287
+ 'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
288
+ '**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
289
+ ),
290
+ );
291
+ }
292
+
293
+ public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
294
+ {
295
+ return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
296
+ }
297
+
298
+ public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
299
+ {
300
+ $stream = $parser->getStream();
301
+ $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
302
+ $class = $this->getTestNodeClass($parser, $name, $node->getLine());
303
+ $arguments = null;
304
+ if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
305
+ $arguments = $parser->getExpressionParser()->parseArguments(true);
306
+ }
307
+
308
+ return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
309
+ }
310
+
311
+ protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
312
+ {
313
+ $env = $parser->getEnvironment();
314
+ $testMap = $env->getTests();
315
+ $testName = null;
316
+ if (isset($testMap[$name])) {
317
+ $testName = $name;
318
+ } elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) {
319
+ // try 2-words tests
320
+ $name = $name.' '.$parser->getCurrentToken()->getValue();
321
+
322
+ if (isset($testMap[$name])) {
323
+ $parser->getStream()->next();
324
+
325
+ $testName = $name;
326
+ }
327
+ }
328
+
329
+ if (null === $testName) {
330
+ $message = sprintf('The test "%s" does not exist', $name);
331
+ if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
332
+ $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
333
+ }
334
+
335
+ throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
336
+ }
337
+
338
+ if ($testMap[$name] instanceof Twig_SimpleTest) {
339
+ return $testMap[$name]->getNodeClass();
340
+ }
341
+
342
+ return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test';
343
+ }
344
+
345
+ /**
346
+ * Returns the name of the extension.
347
+ *
348
+ * @return string The extension name
349
+ */
350
+ public function getName()
351
+ {
352
+ return 'core';
353
+ }
354
+ }
355
+
356
+ /**
357
+ * Cycles over a value.
358
+ *
359
+ * @param ArrayAccess|array $values An array or an ArrayAccess instance
360
+ * @param int $position The cycle position
361
+ *
362
+ * @return string The next value in the cycle
363
+ */
364
+ function twig_cycle($values, $position)
365
+ {
366
+ if (!is_array($values) && !$values instanceof ArrayAccess) {
367
+ return $values;
368
+ }
369
+
370
+ return $values[$position % count($values)];
371
+ }
372
+
373
+ /**
374
+ * Returns a random value depending on the supplied parameter type:
375
+ * - a random item from a Traversable or array
376
+ * - a random character from a string
377
+ * - a random integer between 0 and the integer parameter
378
+ *
379
+ * @param Twig_Environment $env A Twig_Environment instance
380
+ * @param Traversable|array|int|string $values The values to pick a random item from
381
+ *
382
+ * @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
383
+ *
384
+ * @return mixed A random value from the given sequence
385
+ */
386
+ function twig_random(Twig_Environment $env, $values = null)
387
+ {
388
+ if (null === $values) {
389
+ return mt_rand();
390
+ }
391
+
392
+ if (is_int($values) || is_float($values)) {
393
+ return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
394
+ }
395
+
396
+ if ($values instanceof Traversable) {
397
+ $values = iterator_to_array($values);
398
+ } elseif (is_string($values)) {
399
+ if ('' === $values) {
400
+ return '';
401
+ }
402
+ if (null !== $charset = $env->getCharset()) {
403
+ if ('UTF-8' != $charset) {
404
+ $values = twig_convert_encoding($values, 'UTF-8', $charset);
405
+ }
406
+
407
+ // unicode version of str_split()
408
+ // split at all positions, but not after the start and not before the end
409
+ $values = preg_split('/(?<!^)(?!$)/u', $values);
410
+
411
+ if ('UTF-8' != $charset) {
412
+ foreach ($values as $i => $value) {
413
+ $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
414
+ }
415
+ }
416
+ } else {
417
+ return $values[mt_rand(0, strlen($values) - 1)];
418
+ }
419
+ }
420
+
421
+ if (!is_array($values)) {
422
+ return $values;
423
+ }
424
+
425
+ if (0 === count($values)) {
426
+ throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
427
+ }
428
+
429
+ return $values[array_rand($values, 1)];
430
+ }
431
+
432
+ /**
433
+ * Converts a date to the given format.
434
+ *
435
+ * <pre>
436
+ * {{ post.published_at|date("m/d/Y") }}
437
+ * </pre>
438
+ *
439
+ * @param Twig_Environment $env A Twig_Environment instance
440
+ * @param DateTime|DateInterval|string $date A date
441
+ * @param string $format A format
442
+ * @param DateTimeZone|string $timezone A timezone
443
+ *
444
+ * @return string The formatted date
445
+ */
446
+ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
447
+ {
448
+ if (null === $format) {
449
+ $formats = $env->getExtension('core')->getDateFormat();
450
+ $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
451
+ }
452
+
453
+ if ($date instanceof DateInterval) {
454
+ return $date->format($format);
455
+ }
456
+
457
+ return twig_date_converter($env, $date, $timezone)->format($format);
458
+ }
459
+
460
+ /**
461
+ * Returns a new date object modified
462
+ *
463
+ * <pre>
464
+ * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
465
+ * </pre>
466
+ *
467
+ * @param Twig_Environment $env A Twig_Environment instance
468
+ * @param DateTime|string $date A date
469
+ * @param string $modifier A modifier string
470
+ *
471
+ * @return DateTime A new date object
472
+ */
473
+ function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
474
+ {
475
+ $date = twig_date_converter($env, $date, false);
476
+ $date->modify($modifier);
477
+
478
+ return $date;
479
+ }
480
+
481
+ /**
482
+ * Converts an input to a DateTime instance.
483
+ *
484
+ * <pre>
485
+ * {% if date(user.created_at) < date('+2days') %}
486
+ * {# do something #}
487
+ * {% endif %}
488
+ * </pre>
489
+ *
490
+ * @param Twig_Environment $env A Twig_Environment instance
491
+ * @param DateTime|string $date A date
492
+ * @param DateTimeZone|string $timezone A timezone
493
+ *
494
+ * @return DateTime A DateTime instance
495
+ */
496
+ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
497
+ {
498
+ // determine the timezone
499
+ if (!$timezone) {
500
+ $defaultTimezone = $env->getExtension('core')->getTimezone();
501
+ } elseif (!$timezone instanceof DateTimeZone) {
502
+ $defaultTimezone = new DateTimeZone($timezone);
503
+ } else {
504
+ $defaultTimezone = $timezone;
505
+ }
506
+
507
+ // immutable dates
508
+ if ($date instanceof DateTimeImmutable) {
509
+ return false !== $timezone ? $date->setTimezone($defaultTimezone) : $date;
510
+ }
511
+
512
+ if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
513
+ $date = clone $date;
514
+ if (false !== $timezone) {
515
+ $date->setTimezone($defaultTimezone);
516
+ }
517
+
518
+ return $date;
519
+ }
520
+
521
+ $asString = (string) $date;
522
+ if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
523
+ $date = '@'.$date;
524
+ }
525
+
526
+ $date = new DateTime($date, $defaultTimezone);
527
+ if (false !== $timezone) {
528
+ $date->setTimezone($defaultTimezone);
529
+ }
530
+
531
+ return $date;
532
+ }
533
+
534
+ /**
535
+ * Rounds a number.
536
+ *
537
+ * @param int|float $value The value to round
538
+ * @param int|float $precision The rounding precision
539
+ * @param string $method The method to use for rounding
540
+ *
541
+ * @return int|float The rounded number
542
+ */
543
+ function twig_round($value, $precision = 0, $method = 'common')
544
+ {
545
+ if ('common' == $method) {
546
+ return round($value, $precision);
547
+ }
548
+
549
+ if ('ceil' != $method && 'floor' != $method) {
550
+ throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.');
551
+ }
552
+
553
+ return $method($value * pow(10, $precision)) / pow(10, $precision);
554
+ }
555
+
556
+ /**
557
+ * Number format filter.
558
+ *
559
+ * All of the formatting options can be left null, in that case the defaults will
560
+ * be used. Supplying any of the parameters will override the defaults set in the
561
+ * environment object.
562
+ *
563
+ * @param Twig_Environment $env A Twig_Environment instance
564
+ * @param mixed $number A float/int/string of the number to format
565
+ * @param int $decimal The number of decimal points to display.
566
+ * @param string $decimalPoint The character(s) to use for the decimal point.
567
+ * @param string $thousandSep The character(s) to use for the thousands separator.
568
+ *
569
+ * @return string The formatted number
570
+ */
571
+ function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
572
+ {
573
+ $defaults = $env->getExtension('core')->getNumberFormat();
574
+ if (null === $decimal) {
575
+ $decimal = $defaults[0];
576
+ }
577
+
578
+ if (null === $decimalPoint) {
579
+ $decimalPoint = $defaults[1];
580
+ }
581
+
582
+ if (null === $thousandSep) {
583
+ $thousandSep = $defaults[2];
584
+ }
585
+
586
+ return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
587
+ }
588
+
589
+ /**
590
+ * URL encodes (RFC 3986) a string as a path segment or an array as a query string.
591
+ *
592
+ * @param string|array $url A URL or an array of query parameters
593
+ *
594
+ * @return string The URL encoded value
595
+ */
596
+ function twig_urlencode_filter($url)
597
+ {
598
+ if (is_array($url)) {
599
+ if (defined('PHP_QUERY_RFC3986')) {
600
+ return http_build_query($url, '', '&', PHP_QUERY_RFC3986);
601
+ }
602
+
603
+ return http_build_query($url, '', '&');
604
+ }
605
+
606
+ return rawurlencode($url);
607
+ }
608
+
609
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
610
+ /**
611
+ * JSON encodes a variable.
612
+ *
613
+ * @param mixed $value The value to encode.
614
+ * @param int $options Not used on PHP 5.2.x
615
+ *
616
+ * @return mixed The JSON encoded value
617
+ */
618
+ function twig_jsonencode_filter($value, $options = 0)
619
+ {
620
+ if ($value instanceof Twig_Markup) {
621
+ $value = (string) $value;
622
+ } elseif (is_array($value)) {
623
+ array_walk_recursive($value, '_twig_markup2string');
624
+ }
625
+
626
+ return json_encode($value);
627
+ }
628
+ } else {
629
+ /**
630
+ * JSON encodes a variable.
631
+ *
632
+ * @param mixed $value The value to encode.
633
+ * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
634
+ *
635
+ * @return mixed The JSON encoded value
636
+ */
637
+ function twig_jsonencode_filter($value, $options = 0)
638
+ {
639
+ if ($value instanceof Twig_Markup) {
640
+ $value = (string) $value;
641
+ } elseif (is_array($value)) {
642
+ array_walk_recursive($value, '_twig_markup2string');
643
+ }
644
+
645
+ return json_encode($value, $options);
646
+ }
647
+ }
648
+
649
+ function _twig_markup2string(&$value)
650
+ {
651
+ if ($value instanceof Twig_Markup) {
652
+ $value = (string) $value;
653
+ }
654
+ }
655
+
656
+ /**
657
+ * Merges an array with another one.
658
+ *
659
+ * <pre>
660
+ * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
661
+ *
662
+ * {% set items = items|merge({ 'peugeot': 'car' }) %}
663
+ *
664
+ * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
665
+ * </pre>
666
+ *
667
+ * @param array $arr1 An array
668
+ * @param array $arr2 An array
669
+ *
670
+ * @return array The merged array
671
+ */
672
+ function twig_array_merge($arr1, $arr2)
673
+ {
674
+ if (!is_array($arr1) || !is_array($arr2)) {
675
+ throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
676
+ }
677
+
678
+ return array_merge($arr1, $arr2);
679
+ }
680
+
681
+ /**
682
+ * Slices a variable.
683
+ *
684
+ * @param Twig_Environment $env A Twig_Environment instance
685
+ * @param mixed $item A variable
686
+ * @param int $start Start of the slice
687
+ * @param int $length Size of the slice
688
+ * @param bool $preserveKeys Whether to preserve key or not (when the input is an array)
689
+ *
690
+ * @return mixed The sliced variable
691
+ */
692
+ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
693
+ {
694
+ if ($item instanceof Traversable) {
695
+ $item = iterator_to_array($item, false);
696
+ }
697
+
698
+ if (is_array($item)) {
699
+ return array_slice($item, $start, $length, $preserveKeys);
700
+ }
701
+
702
+ $item = (string) $item;
703
+
704
+ if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
705
+ return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
706
+ }
707
+
708
+ return null === $length ? substr($item, $start) : substr($item, $start, $length);
709
+ }
710
+
711
+ /**
712
+ * Returns the first element of the item.
713
+ *
714
+ * @param Twig_Environment $env A Twig_Environment instance
715
+ * @param mixed $item A variable
716
+ *
717
+ * @return mixed The first element of the item
718
+ */
719
+ function twig_first(Twig_Environment $env, $item)
720
+ {
721
+ $elements = twig_slice($env, $item, 0, 1, false);
722
+
723
+ return is_string($elements) ? $elements : current($elements);
724
+ }
725
+
726
+ /**
727
+ * Returns the last element of the item.
728
+ *
729
+ * @param Twig_Environment $env A Twig_Environment instance
730
+ * @param mixed $item A variable
731
+ *
732
+ * @return mixed The last element of the item
733
+ */
734
+ function twig_last(Twig_Environment $env, $item)
735
+ {
736
+ $elements = twig_slice($env, $item, -1, 1, false);
737
+
738
+ return is_string($elements) ? $elements : current($elements);
739
+ }
740
+
741
+ /**
742
+ * Joins the values to a string.
743
+ *
744
+ * The separator between elements is an empty string per default, you can define it with the optional parameter.
745
+ *
746
+ * <pre>
747
+ * {{ [1, 2, 3]|join('|') }}
748
+ * {# returns 1|2|3 #}
749
+ *
750
+ * {{ [1, 2, 3]|join }}
751
+ * {# returns 123 #}
752
+ * </pre>
753
+ *
754
+ * @param array $value An array
755
+ * @param string $glue The separator
756
+ *
757
+ * @return string The concatenated string
758
+ */
759
+ function twig_join_filter($value, $glue = '')
760
+ {
761
+ if ($value instanceof Traversable) {
762
+ $value = iterator_to_array($value, false);
763
+ }
764
+
765
+ return implode($glue, (array) $value);
766
+ }
767
+
768
+ /**
769
+ * Splits the string into an array.
770
+ *
771
+ * <pre>
772
+ * {{ "one,two,three"|split(',') }}
773
+ * {# returns [one, two, three] #}
774
+ *
775
+ * {{ "one,two,three,four,five"|split(',', 3) }}
776
+ * {# returns [one, two, "three,four,five"] #}
777
+ *
778
+ * {{ "123"|split('') }}
779
+ * {# returns [1, 2, 3] #}
780
+ *
781
+ * {{ "aabbcc"|split('', 2) }}
782
+ * {# returns [aa, bb, cc] #}
783
+ * </pre>
784
+ *
785
+ * @param string $value A string
786
+ * @param string $delimiter The delimiter
787
+ * @param int $limit The limit
788
+ *
789
+ * @return array The split string as an array
790
+ */
791
+ function twig_split_filter($value, $delimiter, $limit = null)
792
+ {
793
+ if (empty($delimiter)) {
794
+ return str_split($value, null === $limit ? 1 : $limit);
795
+ }
796
+
797
+ return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
798
+ }
799
+
800
+ // The '_default' filter is used internally to avoid using the ternary operator
801
+ // which costs a lot for big contexts (before PHP 5.4). So, on average,
802
+ // a function call is cheaper.
803
+ function _twig_default_filter($value, $default = '')
804
+ {
805
+ if (twig_test_empty($value)) {
806
+ return $default;
807
+ }
808
+
809
+ return $value;
810
+ }
811
+
812
+ /**
813
+ * Returns the keys for the given array.
814
+ *
815
+ * It is useful when you want to iterate over the keys of an array:
816
+ *
817
+ * <pre>
818
+ * {% for key in array|keys %}
819
+ * {# ... #}
820
+ * {% endfor %}
821
+ * </pre>
822
+ *
823
+ * @param array $array An array
824
+ *
825
+ * @return array The keys
826
+ */
827
+ function twig_get_array_keys_filter($array)
828
+ {
829
+ if (is_object($array) && $array instanceof Traversable) {
830
+ return array_keys(iterator_to_array($array));
831
+ }
832
+
833
+ if (!is_array($array)) {
834
+ return array();
835
+ }
836
+
837
+ return array_keys($array);
838
+ }
839
+
840
+ /**
841
+ * Reverses a variable.
842
+ *
843
+ * @param Twig_Environment $env A Twig_Environment instance
844
+ * @param array|Traversable|string $item An array, a Traversable instance, or a string
845
+ * @param bool $preserveKeys Whether to preserve key or not
846
+ *
847
+ * @return mixed The reversed input
848
+ */
849
+ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
850
+ {
851
+ if (is_object($item) && $item instanceof Traversable) {
852
+ return array_reverse(iterator_to_array($item), $preserveKeys);
853
+ }
854
+
855
+ if (is_array($item)) {
856
+ return array_reverse($item, $preserveKeys);
857
+ }
858
+
859
+ if (null !== $charset = $env->getCharset()) {
860
+ $string = (string) $item;
861
+
862
+ if ('UTF-8' != $charset) {
863
+ $item = twig_convert_encoding($string, 'UTF-8', $charset);
864
+ }
865
+
866
+ preg_match_all('/./us', $item, $matches);
867
+
868
+ $string = implode('', array_reverse($matches[0]));
869
+
870
+ if ('UTF-8' != $charset) {
871
+ $string = twig_convert_encoding($string, $charset, 'UTF-8');
872
+ }
873
+
874
+ return $string;
875
+ }
876
+
877
+ return strrev((string) $item);
878
+ }
879
+
880
+ /**
881
+ * Sorts an array.
882
+ *
883
+ * @param array $array An array
884
+ */
885
+ function twig_sort_filter($array)
886
+ {
887
+ asort($array);
888
+
889
+ return $array;
890
+ }
891
+
892
+ /* used internally */
893
+ function twig_in_filter($value, $compare)
894
+ {
895
+ if (is_array($compare)) {
896
+ return in_array($value, $compare, is_object($value));
897
+ } elseif (is_string($compare)) {
898
+ if (!strlen($value)) {
899
+ return empty($compare);
900
+ }
901
+
902
+ return false !== strpos($compare, (string) $value);
903
+ } elseif ($compare instanceof Traversable) {
904
+ return in_array($value, iterator_to_array($compare, false), is_object($value));
905
+ }
906
+
907
+ return false;
908
+ }
909
+
910
+ /**
911
+ * Escapes a string.
912
+ *
913
+ * @param Twig_Environment $env A Twig_Environment instance
914
+ * @param string $string The value to be escaped
915
+ * @param string $strategy The escaping strategy
916
+ * @param string $charset The charset
917
+ * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
918
+ */
919
+ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
920
+ {
921
+ if ($autoescape && $string instanceof Twig_Markup) {
922
+ return $string;
923
+ }
924
+
925
+ if (!is_string($string)) {
926
+ if (is_object($string) && method_exists($string, '__toString')) {
927
+ $string = (string) $string;
928
+ } else {
929
+ return $string;
930
+ }
931
+ }
932
+
933
+ if (null === $charset) {
934
+ $charset = $env->getCharset();
935
+ }
936
+
937
+ switch ($strategy) {
938
+ case 'html':
939
+ // see http://php.net/htmlspecialchars
940
+
941
+ // Using a static variable to avoid initializing the array
942
+ // each time the function is called. Moving the declaration on the
943
+ // top of the function slow downs other escaping strategies.
944
+ static $htmlspecialcharsCharsets;
945
+
946
+ if (null === $htmlspecialcharsCharsets) {
947
+ if ('hiphop' === substr(PHP_VERSION, -6)) {
948
+ $htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true);
949
+ } else {
950
+ $htmlspecialcharsCharsets = array(
951
+ 'ISO-8859-1' => true, 'ISO8859-1' => true,
952
+ 'ISO-8859-15' => true, 'ISO8859-15' => true,
953
+ 'utf-8' => true, 'UTF-8' => true,
954
+ 'CP866' => true, 'IBM866' => true, '866' => true,
955
+ 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
956
+ '1251' => true,
957
+ 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
958
+ 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
959
+ 'BIG5' => true, '950' => true,
960
+ 'GB2312' => true, '936' => true,
961
+ 'BIG5-HKSCS' => true,
962
+ 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
963
+ 'EUC-JP' => true, 'EUCJP' => true,
964
+ 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
965
+ );
966
+ }
967
+ }
968
+
969
+ if (isset($htmlspecialcharsCharsets[$charset])) {
970
+ return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
971
+ }
972
+
973
+ if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
974
+ // cache the lowercase variant for future iterations
975
+ $htmlspecialcharsCharsets[$charset] = true;
976
+
977
+ return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
978
+ }
979
+
980
+ $string = twig_convert_encoding($string, 'UTF-8', $charset);
981
+ $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
982
+
983
+ return twig_convert_encoding($string, $charset, 'UTF-8');
984
+
985
+ case 'js':
986
+ // escape all non-alphanumeric characters
987
+ // into their \xHH or \uHHHH representations
988
+ if ('UTF-8' != $charset) {
989
+ $string = twig_convert_encoding($string, 'UTF-8', $charset);
990
+ }
991
+
992
+ if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
993
+ throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
994
+ }
995
+
996
+ $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
997
+
998
+ if ('UTF-8' != $charset) {
999
+ $string = twig_convert_encoding($string, $charset, 'UTF-8');
1000
+ }
1001
+
1002
+ return $string;
1003
+
1004
+ case 'css':
1005
+ if ('UTF-8' != $charset) {
1006
+ $string = twig_convert_encoding($string, 'UTF-8', $charset);
1007
+ }
1008
+
1009
+ if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
1010
+ throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
1011
+ }
1012
+
1013
+ $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
1014
+
1015
+ if ('UTF-8' != $charset) {
1016
+ $string = twig_convert_encoding($string, $charset, 'UTF-8');
1017
+ }
1018
+
1019
+ return $string;
1020
+
1021
+ case 'html_attr':
1022
+ if ('UTF-8' != $charset) {
1023
+ $string = twig_convert_encoding($string, 'UTF-8', $charset);
1024
+ }
1025
+
1026
+ if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
1027
+ throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
1028
+ }
1029
+
1030
+ $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
1031
+
1032
+ if ('UTF-8' != $charset) {
1033
+ $string = twig_convert_encoding($string, $charset, 'UTF-8');
1034
+ }
1035
+
1036
+ return $string;
1037
+
1038
+ case 'url':
1039
+ // hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.*
1040
+ // at that point however PHP 5.2.* support can be removed
1041
+ if (PHP_VERSION < '5.3.0') {
1042
+ return str_replace('%7E', '~', rawurlencode($string));
1043
+ }
1044
+
1045
+ return rawurlencode($string);
1046
+
1047
+ default:
1048
+ static $escapers;
1049
+
1050
+ if (null === $escapers) {
1051
+ $escapers = $env->getExtension('core')->getEscapers();
1052
+ }
1053
+
1054
+ if (isset($escapers[$strategy])) {
1055
+ return call_user_func($escapers[$strategy], $env, $string, $charset);
1056
+ }
1057
+
1058
+ $validStrategies = implode(', ', array_merge(array('html', 'js', 'url', 'css', 'html_attr'), array_keys($escapers)));
1059
+
1060
+ throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
1061
+ }
1062
+ }
1063
+
1064
+ /* used internally */
1065
+ function twig_escape_filter_is_safe(Twig_Node $filterArgs)
1066
+ {
1067
+ foreach ($filterArgs as $arg) {
1068
+ if ($arg instanceof Twig_Node_Expression_Constant) {
1069
+ return array($arg->getAttribute('value'));
1070
+ }
1071
+
1072
+ return array();
1073
+ }
1074
+
1075
+ return array('html');
1076
+ }
1077
+
1078
+ if (function_exists('mb_convert_encoding')) {
1079
+ function twig_convert_encoding($string, $to, $from)
1080
+ {
1081
+ return mb_convert_encoding($string, $to, $from);
1082
+ }
1083
+ } elseif (function_exists('iconv')) {
1084
+ function twig_convert_encoding($string, $to, $from)
1085
+ {
1086
+ return iconv($from, $to, $string);
1087
+ }
1088
+ } else {
1089
+ function twig_convert_encoding($string, $to, $from)
1090
+ {
1091
+ throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
1092
+ }
1093
+ }
1094
+
1095
+ function _twig_escape_js_callback($matches)
1096
+ {
1097
+ $char = $matches[0];
1098
+
1099
+ // \xHH
1100
+ if (!isset($char[1])) {
1101
+ return '\\x'.strtoupper(substr('00'.bin2hex($char), -2));
1102
+ }
1103
+
1104
+ // \uHHHH
1105
+ $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
1106
+
1107
+ return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
1108
+ }
1109
+
1110
+ function _twig_escape_css_callback($matches)
1111
+ {
1112
+ $char = $matches[0];
1113
+
1114
+ // \xHH
1115
+ if (!isset($char[1])) {
1116
+ $hex = ltrim(strtoupper(bin2hex($char)), '0');
1117
+ if (0 === strlen($hex)) {
1118
+ $hex = '0';
1119
+ }
1120
+
1121
+ return '\\'.$hex.' ';
1122
+ }
1123
+
1124
+ // \uHHHH
1125
+ $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
1126
+
1127
+ return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
1128
+ }
1129
+
1130
+ /**
1131
+ * This function is adapted from code coming from Zend Framework.
1132
+ *
1133
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
1134
+ * @license http://framework.zend.com/license/new-bsd New BSD License
1135
+ */
1136
+ function _twig_escape_html_attr_callback($matches)
1137
+ {
1138
+ /*
1139
+ * While HTML supports far more named entities, the lowest common denominator
1140
+ * has become HTML5's XML Serialisation which is restricted to the those named
1141
+ * entities that XML supports. Using HTML entities would result in this error:
1142
+ * XML Parsing Error: undefined entity
1143
+ */
1144
+ static $entityMap = array(
1145
+ 34 => 'quot', /* quotation mark */
1146
+ 38 => 'amp', /* ampersand */
1147
+ 60 => 'lt', /* less-than sign */
1148
+ 62 => 'gt', /* greater-than sign */
1149
+ );
1150
+
1151
+ $chr = $matches[0];
1152
+ $ord = ord($chr);
1153
+
1154
+ /**
1155
+ * The following replaces characters undefined in HTML with the
1156
+ * hex entity for the Unicode replacement character.
1157
+ */
1158
+ if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
1159
+ return '&#xFFFD;';
1160
+ }
1161
+
1162
+ /**
1163
+ * Check if the current character to escape has a name entity we should
1164
+ * replace it with while grabbing the hex value of the character.
1165
+ */
1166
+ if (strlen($chr) == 1) {
1167
+ $hex = strtoupper(substr('00'.bin2hex($chr), -2));
1168
+ } else {
1169
+ $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8');
1170
+ $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
1171
+ }
1172
+
1173
+ $int = hexdec($hex);
1174
+ if (array_key_exists($int, $entityMap)) {
1175
+ return sprintf('&%s;', $entityMap[$int]);
1176
+ }
1177
+
1178
+ /**
1179
+ * Per OWASP recommendations, we'll use hex entities for any other
1180
+ * characters where a named entity does not exist.
1181
+ */
1182
+
1183
+ return sprintf('&#x%s;', $hex);
1184
+ }
1185
+
1186
+ // add multibyte extensions if possible
1187
+ if (function_exists('mb_get_info')) {
1188
+ /**
1189
+ * Returns the length of a variable.
1190
+ *
1191
+ * @param Twig_Environment $env A Twig_Environment instance
1192
+ * @param mixed $thing A variable
1193
+ *
1194
+ * @return int The length of the value
1195
+ */
1196
+ function twig_length_filter(Twig_Environment $env, $thing)
1197
+ {
1198
+ return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing);
1199
+ }
1200
+
1201
+ /**
1202
+ * Converts a string to uppercase.
1203
+ *
1204
+ * @param Twig_Environment $env A Twig_Environment instance
1205
+ * @param string $string A string
1206
+ *
1207
+ * @return string The uppercased string
1208
+ */
1209
+ function twig_upper_filter(Twig_Environment $env, $string)
1210
+ {
1211
+ if (null !== ($charset = $env->getCharset())) {
1212
+ return mb_strtoupper($string, $charset);
1213
+ }
1214
+
1215
+ return strtoupper($string);
1216
+ }
1217
+
1218
+ /**
1219
+ * Converts a string to lowercase.
1220
+ *
1221
+ * @param Twig_Environment $env A Twig_Environment instance
1222
+ * @param string $string A string
1223
+ *
1224
+ * @return string The lowercased string
1225
+ */
1226
+ function twig_lower_filter(Twig_Environment $env, $string)
1227
+ {
1228
+ if (null !== ($charset = $env->getCharset())) {
1229
+ return mb_strtolower($string, $charset);
1230
+ }
1231
+
1232
+ return strtolower($string);
1233
+ }
1234
+
1235
+ /**
1236
+ * Returns a titlecased string.
1237
+ *
1238
+ * @param Twig_Environment $env A Twig_Environment instance
1239
+ * @param string $string A string
1240
+ *
1241
+ * @return string The titlecased string
1242
+ */
1243
+ function twig_title_string_filter(Twig_Environment $env, $string)
1244
+ {
1245
+ if (null !== ($charset = $env->getCharset())) {
1246
+ return mb_convert_case($string, MB_CASE_TITLE, $charset);
1247
+ }
1248
+
1249
+ return ucwords(strtolower($string));
1250
+ }
1251
+
1252
+ /**
1253
+ * Returns a capitalized string.
1254
+ *
1255
+ * @param Twig_Environment $env A Twig_Environment instance
1256
+ * @param string $string A string
1257
+ *
1258
+ * @return string The capitalized string
1259
+ */
1260
+ function twig_capitalize_string_filter(Twig_Environment $env, $string)
1261
+ {
1262
+ if (null !== ($charset = $env->getCharset())) {
1263
+ return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
1264
+ mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
1265
+ }
1266
+
1267
+ return ucfirst(strtolower($string));
1268
+ }
1269
+ }
1270
+ // and byte fallback
1271
+ else {
1272
+ /**
1273
+ * Returns the length of a variable.
1274
+ *
1275
+ * @param Twig_Environment $env A Twig_Environment instance
1276
+ * @param mixed $thing A variable
1277
+ *
1278
+ * @return int The length of the value
1279
+ */
1280
+ function twig_length_filter(Twig_Environment $env, $thing)
1281
+ {
1282
+ return is_scalar($thing) ? strlen($thing) : count($thing);
1283
+ }
1284
+
1285
+ /**
1286
+ * Returns a titlecased string.
1287
+ *
1288
+ * @param Twig_Environment $env A Twig_Environment instance
1289
+ * @param string $string A string
1290
+ *
1291
+ * @return string The titlecased string
1292
+ */
1293
+ function twig_title_string_filter(Twig_Environment $env, $string)
1294
+ {
1295
+ return ucwords(strtolower($string));
1296
+ }
1297
+
1298
+ /**
1299
+ * Returns a capitalized string.
1300
+ *
1301
+ * @param Twig_Environment $env A Twig_Environment instance
1302
+ * @param string $string A string
1303
+ *
1304
+ * @return string The capitalized string
1305
+ */
1306
+ function twig_capitalize_string_filter(Twig_Environment $env, $string)
1307
+ {
1308
+ return ucfirst(strtolower($string));
1309
+ }
1310
+ }
1311
+
1312
+ /* used internally */
1313
+ function twig_ensure_traversable($seq)
1314
+ {
1315
+ if ($seq instanceof Traversable || is_array($seq)) {
1316
+ return $seq;
1317
+ }
1318
+
1319
+ return array();
1320
+ }
1321
+
1322
+ /**
1323
+ * Checks if a variable is empty.
1324
+ *
1325
+ * <pre>
1326
+ * {# evaluates to true if the foo variable is null, false, or the empty string #}
1327
+ * {% if foo is empty %}
1328
+ * {# ... #}
1329
+ * {% endif %}
1330
+ * </pre>
1331
+ *
1332
+ * @param mixed $value A variable
1333
+ *
1334
+ * @return bool true if the value is empty, false otherwise
1335
+ */
1336
+ function twig_test_empty($value)
1337
+ {
1338
+ if ($value instanceof Countable) {
1339
+ return 0 == count($value);
1340
+ }
1341
+
1342
+ return '' === $value || false === $value || null === $value || array() === $value;
1343
+ }
1344
+
1345
+ /**
1346
+ * Checks if a variable is traversable.
1347
+ *
1348
+ * <pre>
1349
+ * {# evaluates to true if the foo variable is an array or a traversable object #}
1350
+ * {% if foo is traversable %}
1351
+ * {# ... #}
1352
+ * {% endif %}
1353
+ * </pre>
1354
+ *
1355
+ * @param mixed $value A variable
1356
+ *
1357
+ * @return bool true if the value is traversable
1358
+ */
1359
+ function twig_test_iterable($value)
1360
+ {
1361
+ return $value instanceof Traversable || is_array($value);
1362
+ }
1363
+
1364
+ /**
1365
+ * Renders a template.
1366
+ *
1367
+ * @param string|array $template The template to render or an array of templates to try consecutively
1368
+ * @param array $variables The variables to pass to the template
1369
+ * @param bool $with_context Whether to pass the current context variables or not
1370
+ * @param bool $ignore_missing Whether to ignore missing templates or not
1371
+ * @param bool $sandboxed Whether to sandbox the template or not
1372
+ *
1373
+ * @return string The rendered template
1374
+ */
1375
+ function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)
1376
+ {
1377
+ $alreadySandboxed = false;
1378
+ $sandbox = null;
1379
+ if ($withContext) {
1380
+ $variables = array_merge($context, $variables);
1381
+ }
1382
+
1383
+ if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) {
1384
+ $sandbox = $env->getExtension('sandbox');
1385
+ if (!$alreadySandboxed = $sandbox->isSandboxed()) {
1386
+ $sandbox->enableSandbox();
1387
+ }
1388
+ }
1389
+
1390
+ try {
1391
+ return $env->resolveTemplate($template)->render($variables);
1392
+ } catch (Twig_Error_Loader $e) {
1393
+ if (!$ignoreMissing) {
1394
+ throw $e;
1395
+ }
1396
+ }
1397
+
1398
+ if ($isSandboxed && !$alreadySandboxed) {
1399
+ $sandbox->disableSandbox();
1400
+ }
1401
+ }
1402
+
1403
+ /**
1404
+ * Returns a template content without rendering it.
1405
+ *
1406
+ * @param string $name The template name
1407
+ *
1408
+ * @return string The template source
1409
+ */
1410
+ function twig_source(Twig_Environment $env, $name)
1411
+ {
1412
+ return $env->getLoader()->getSource($name);
1413
+ }
1414
+
1415
+ /**
1416
+ * Provides the ability to get constants from instances as well as class/global constants.
1417
+ *
1418
+ * @param string $constant The name of the constant
1419
+ * @param null|object $object The object to get the constant from
1420
+ *
1421
+ * @return string
1422
+ */
1423
+ function twig_constant($constant, $object = null)
1424
+ {
1425
+ if (null !== $object) {
1426
+ $constant = get_class($object).'::'.$constant;
1427
+ }
1428
+
1429
+ return constant($constant);
1430
+ }
1431
+
1432
+ /**
1433
+ * Batches item.
1434
+ *
1435
+ * @param array $items An array of items
1436
+ * @param int $size The size of the batch
1437
+ * @param mixed $fill A value used to fill missing items
1438
+ *
1439
+ * @return array
1440
+ */
1441
+ function twig_array_batch($items, $size, $fill = null)
1442
+ {
1443
+ if ($items instanceof Traversable) {
1444
+ $items = iterator_to_array($items, false);
1445
+ }
1446
+
1447
+ $size = ceil($size);
1448
+
1449
+ $result = array_chunk($items, $size, true);
1450
+
1451
+ if (null !== $fill) {
1452
+ $last = count($result) - 1;
1453
+ if ($fillCount = $size - count($result[$last])) {
1454
+ $result[$last] = array_merge(
1455
+ $result[$last],
1456
+ array_fill(0, $fillCount, $fill)
1457
+ );
1458
+ }
1459
+ }
1460
+
1461
+ return $result;
1462
+ }
classes/Twig/Extension/Debug.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Extension_Debug extends Twig_Extension
12
+ {
13
+ /**
14
+ * Returns a list of global functions to add to the existing list.
15
+ *
16
+ * @return array An array of global functions
17
+ */
18
+ public function getFunctions()
19
+ {
20
+ // dump is safe if var_dump is overridden by xdebug
21
+ $isDumpOutputHtmlSafe = extension_loaded('xdebug')
22
+ // false means that it was not set (and the default is on) or it explicitly enabled
23
+ && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
24
+ // false means that it was not set (and the default is on) or it explicitly enabled
25
+ // xdebug.overload_var_dump produces HTML only when html_errors is also enabled
26
+ && (false === ini_get('html_errors') || ini_get('html_errors'))
27
+ || 'cli' === php_sapi_name()
28
+ ;
29
+
30
+ return array(
31
+ new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
32
+ );
33
+ }
34
+
35
+ /**
36
+ * Returns the name of the extension.
37
+ *
38
+ * @return string The extension name
39
+ */
40
+ public function getName()
41
+ {
42
+ return 'debug';
43
+ }
44
+ }
45
+
46
+ function twig_var_dump(Twig_Environment $env, $context)
47
+ {
48
+ if (!$env->isDebug()) {
49
+ return;
50
+ }
51
+
52
+ ob_start();
53
+
54
+ $count = func_num_args();
55
+ if (2 === $count) {
56
+ $vars = array();
57
+ foreach ($context as $key => $value) {
58
+ if (!$value instanceof Twig_Template) {
59
+ $vars[$key] = $value;
60
+ }
61
+ }
62
+
63
+ var_dump($vars);
64
+ } else {
65
+ for ($i = 2; $i < $count; $i++) {
66
+ var_dump(func_get_arg($i));
67
+ }
68
+ }
69
+
70
+ return ob_get_clean();
71
+ }
classes/Twig/Extension/Escaper.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Extension_Escaper extends Twig_Extension
12
+ {
13
+ protected $defaultStrategy;
14
+
15
+ public function __construct($defaultStrategy = 'html')
16
+ {
17
+ $this->setDefaultStrategy($defaultStrategy);
18
+ }
19
+
20
+ /**
21
+ * Returns the token parser instances to add to the existing list.
22
+ *
23
+ * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
24
+ */
25
+ public function getTokenParsers()
26
+ {
27
+ return array(new Twig_TokenParser_AutoEscape());
28
+ }
29
+
30
+ /**
31
+ * Returns the node visitor instances to add to the existing list.
32
+ *
33
+ * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
34
+ */
35
+ public function getNodeVisitors()
36
+ {
37
+ return array(new Twig_NodeVisitor_Escaper());
38
+ }
39
+
40
+ /**
41
+ * Returns a list of filters to add to the existing list.
42
+ *
43
+ * @return array An array of filters
44
+ */
45
+ public function getFilters()
46
+ {
47
+ return array(
48
+ new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))),
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Sets the default strategy to use when not defined by the user.
54
+ *
55
+ * The strategy can be a valid PHP callback that takes the template
56
+ * "filename" as an argument and returns the strategy to use.
57
+ *
58
+ * @param mixed $defaultStrategy An escaping strategy
59
+ */
60
+ public function setDefaultStrategy($defaultStrategy)
61
+ {
62
+ // for BC
63
+ if (true === $defaultStrategy) {
64
+ $defaultStrategy = 'html';
65
+ }
66
+
67
+ $this->defaultStrategy = $defaultStrategy;
68
+ }
69
+
70
+ /**
71
+ * Gets the default strategy to use when not defined by the user.
72
+ *
73
+ * @param string $filename The template "filename"
74
+ *
75
+ * @return string The default strategy to use for the template
76
+ */
77
+ public function getDefaultStrategy($filename)
78
+ {
79
+ // disable string callables to avoid calling a function named html or js,
80
+ // or any other upcoming escaping strategy
81
+ if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) {
82
+ return call_user_func($this->defaultStrategy, $filename);
83
+ }
84
+
85
+ return $this->defaultStrategy;
86
+ }
87
+
88
+ /**
89
+ * Returns the name of the extension.
90
+ *
91
+ * @return string The extension name
92
+ */
93
+ public function getName()
94
+ {
95
+ return 'escaper';
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Marks a variable as being safe.
101
+ *
102
+ * @param string $string A PHP variable
103
+ */
104
+ function twig_raw_filter($string)
105
+ {
106
+ return $string;
107
+ }
classes/Twig/Extension/Optimizer.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Extension_Optimizer extends Twig_Extension
12
+ {
13
+ protected $optimizers;
14
+
15
+ public function __construct($optimizers = -1)
16
+ {
17
+ $this->optimizers = $optimizers;
18
+ }
19
+
20
+ /**
21
+ * {@inheritdoc}
22
+ */
23
+ public function getNodeVisitors()
24
+ {
25
+ return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
26
+ }
27
+
28
+ /**
29
+ * {@inheritdoc}
30
+ */
31
+ public function getName()
32
+ {
33
+ return 'optimizer';
34
+ }
35
+ }
classes/Twig/Extension/Sandbox.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Extension_Sandbox extends Twig_Extension
12
+ {
13
+ protected $sandboxedGlobally;
14
+ protected $sandboxed;
15
+ protected $policy;
16
+
17
+ public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
18
+ {
19
+ $this->policy = $policy;
20
+ $this->sandboxedGlobally = $sandboxed;
21
+ }
22
+
23
+ /**
24
+ * Returns the token parser instances to add to the existing list.
25
+ *
26
+ * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
27
+ */
28
+ public function getTokenParsers()
29
+ {
30
+ return array(new Twig_TokenParser_Sandbox());
31
+ }
32
+
33
+ /**
34
+ * Returns the node visitor instances to add to the existing list.
35
+ *
36
+ * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
37
+ */
38
+ public function getNodeVisitors()
39
+ {
40
+ return array(new Twig_NodeVisitor_Sandbox());
41
+ }
42
+
43
+ public function enableSandbox()
44
+ {
45
+ $this->sandboxed = true;
46
+ }
47
+
48
+ public function disableSandbox()
49
+ {
50
+ $this->sandboxed = false;
51
+ }
52
+
53
+ public function isSandboxed()
54
+ {
55
+ return $this->sandboxedGlobally || $this->sandboxed;
56
+ }
57
+
58
+ public function isSandboxedGlobally()
59
+ {
60
+ return $this->sandboxedGlobally;
61
+ }
62
+
63
+ public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy)
64
+ {
65
+ $this->policy = $policy;
66
+ }
67
+
68
+ public function getSecurityPolicy()
69
+ {
70
+ return $this->policy;
71
+ }
72
+
73
+ public function checkSecurity($tags, $filters, $functions)
74
+ {
75
+ if ($this->isSandboxed()) {
76
+ $this->policy->checkSecurity($tags, $filters, $functions);
77
+ }
78
+ }
79
+
80
+ public function checkMethodAllowed($obj, $method)
81
+ {
82
+ if ($this->isSandboxed()) {
83
+ $this->policy->checkMethodAllowed($obj, $method);
84
+ }
85
+ }
86
+
87
+ public function checkPropertyAllowed($obj, $method)
88
+ {
89
+ if ($this->isSandboxed()) {
90
+ $this->policy->checkPropertyAllowed($obj, $method);
91
+ }
92
+ }
93
+
94
+ public function ensureToStringAllowed($obj)
95
+ {
96
+ if ($this->isSandboxed() && is_object($obj)) {
97
+ $this->policy->checkMethodAllowed($obj, '__toString');
98
+ }
99
+
100
+ return $obj;
101
+ }
102
+
103
+ /**
104
+ * Returns the name of the extension.
105
+ *
106
+ * @return string The extension name
107
+ */
108
+ public function getName()
109
+ {
110
+ return 'sandbox';
111
+ }
112
+ }
classes/Twig/Extension/Staging.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Internal class.
14
+ *
15
+ * This class is used by Twig_Environment as a staging area and must not be used directly.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ */
19
+ class Twig_Extension_Staging extends Twig_Extension
20
+ {
21
+ protected $functions = array();
22
+ protected $filters = array();
23
+ protected $visitors = array();
24
+ protected $tokenParsers = array();
25
+ protected $globals = array();
26
+ protected $tests = array();
27
+
28
+ public function addFunction($name, $function)
29
+ {
30
+ $this->functions[$name] = $function;
31
+ }
32
+
33
+ /**
34
+ * {@inheritdoc}
35
+ */
36
+ public function getFunctions()
37
+ {
38
+ return $this->functions;
39
+ }
40
+
41
+ public function addFilter($name, $filter)
42
+ {
43
+ $this->filters[$name] = $filter;
44
+ }
45
+
46
+ /**
47
+ * {@inheritdoc}
48
+ */
49
+ public function getFilters()
50
+ {
51
+ return $this->filters;
52
+ }
53
+
54
+ public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
55
+ {
56
+ $this->visitors[] = $visitor;
57
+ }
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ */
62
+ public function getNodeVisitors()
63
+ {
64
+ return $this->visitors;
65
+ }
66
+
67
+ public function addTokenParser(Twig_TokenParserInterface $parser)
68
+ {
69
+ $this->tokenParsers[] = $parser;
70
+ }
71
+
72
+ /**
73
+ * {@inheritdoc}
74
+ */
75
+ public function getTokenParsers()
76
+ {
77
+ return $this->tokenParsers;
78
+ }
79
+
80
+ public function addGlobal($name, $value)
81
+ {
82
+ $this->globals[$name] = $value;
83
+ }
84
+
85
+ /**
86
+ * {@inheritdoc}
87
+ */
88
+ public function getGlobals()
89
+ {
90
+ return $this->globals;
91
+ }
92
+
93
+ public function addTest($name, $test)
94
+ {
95
+ $this->tests[$name] = $test;
96
+ }
97
+
98
+ /**
99
+ * {@inheritdoc}
100
+ */
101
+ public function getTests()
102
+ {
103
+ return $this->tests;
104
+ }
105
+
106
+ /**
107
+ * {@inheritdoc}
108
+ */
109
+ public function getName()
110
+ {
111
+ return 'staging';
112
+ }
113
+ }
classes/Twig/Extension/StringLoader.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Extension_StringLoader extends Twig_Extension
12
+ {
13
+ /**
14
+ * {@inheritdoc}
15
+ */
16
+ public function getFunctions()
17
+ {
18
+ return array(
19
+ new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)),
20
+ );
21
+ }
22
+
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function getName()
27
+ {
28
+ return 'string_loader';
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Loads a template from a string.
34
+ *
35
+ * <pre>
36
+ * {{ include(template_from_string("Hello {{ name }}")) }}
37
+ * </pre>
38
+ *
39
+ * @param Twig_Environment $env A Twig_Environment instance
40
+ * @param string $template A template as a string
41
+ *
42
+ * @return Twig_Template A Twig_Template instance
43
+ */
44
+ function twig_template_from_string(Twig_Environment $env, $template)
45
+ {
46
+ $name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false));
47
+
48
+ $loader = new Twig_Loader_Chain(array(
49
+ new Twig_Loader_Array(array($name => $template)),
50
+ $current = $env->getLoader(),
51
+ ));
52
+
53
+ $env->setLoader($loader);
54
+ try {
55
+ $template = $env->loadTemplate($name);
56
+ } catch (Exception $e) {
57
+ $env->setLoader($current);
58
+
59
+ throw $e;
60
+ }
61
+ $env->setLoader($current);
62
+
63
+ return $template;
64
+ }
classes/Twig/ExtensionInterface.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface implemented by extension classes.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ interface Twig_ExtensionInterface
18
+ {
19
+ /**
20
+ * Initializes the runtime environment.
21
+ *
22
+ * This is where you can load some file that contains filter functions for instance.
23
+ *
24
+ * @param Twig_Environment $environment The current Twig_Environment instance
25
+ */
26
+ public function initRuntime(Twig_Environment $environment);
27
+
28
+ /**
29
+ * Returns the token parser instances to add to the existing list.
30
+ *
31
+ * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
32
+ */
33
+ public function getTokenParsers();
34
+
35
+ /**
36
+ * Returns the node visitor instances to add to the existing list.
37
+ *
38
+ * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
39
+ */
40
+ public function getNodeVisitors();
41
+
42
+ /**
43
+ * Returns a list of filters to add to the existing list.
44
+ *
45
+ * @return array An array of filters
46
+ */
47
+ public function getFilters();
48
+
49
+ /**
50
+ * Returns a list of tests to add to the existing list.
51
+ *
52
+ * @return array An array of tests
53
+ */
54
+ public function getTests();
55
+
56
+ /**
57
+ * Returns a list of functions to add to the existing list.
58
+ *
59
+ * @return array An array of functions
60
+ */
61
+ public function getFunctions();
62
+
63
+ /**
64
+ * Returns a list of operators to add to the existing list.
65
+ *
66
+ * @return array An array of operators
67
+ */
68
+ public function getOperators();
69
+
70
+ /**
71
+ * Returns a list of global variables to add to the existing list.
72
+ *
73
+ * @return array An array of global variables
74
+ */
75
+ public function getGlobals();
76
+
77
+ /**
78
+ * Returns the name of the extension.
79
+ *
80
+ * @return string The extension name
81
+ */
82
+ public function getName();
83
+ }
classes/Twig/Filter.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template filter.
14
+ *
15
+ * Use Twig_SimpleFilter instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
21
+ {
22
+ protected $options;
23
+ protected $arguments = array();
24
+
25
+ public function __construct(array $options = array())
26
+ {
27
+ $this->options = array_merge(array(
28
+ 'needs_environment' => false,
29
+ 'needs_context' => false,
30
+ 'pre_escape' => null,
31
+ 'preserves_safety' => null,
32
+ 'callable' => null,
33
+ ), $options);
34
+ }
35
+
36
+ public function setArguments($arguments)
37
+ {
38
+ $this->arguments = $arguments;
39
+ }
40
+
41
+ public function getArguments()
42
+ {
43
+ return $this->arguments;
44
+ }
45
+
46
+ public function needsEnvironment()
47
+ {
48
+ return $this->options['needs_environment'];
49
+ }
50
+
51
+ public function needsContext()
52
+ {
53
+ return $this->options['needs_context'];
54
+ }
55
+
56
+ public function getSafe(Twig_Node $filterArgs)
57
+ {
58
+ if (isset($this->options['is_safe'])) {
59
+ return $this->options['is_safe'];
60
+ }
61
+
62
+ if (isset($this->options['is_safe_callback'])) {
63
+ return call_user_func($this->options['is_safe_callback'], $filterArgs);
64
+ }
65
+ }
66
+
67
+ public function getPreservesSafety()
68
+ {
69
+ return $this->options['preserves_safety'];
70
+ }
71
+
72
+ public function getPreEscape()
73
+ {
74
+ return $this->options['pre_escape'];
75
+ }
76
+
77
+ public function getCallable()
78
+ {
79
+ return $this->options['callable'];
80
+ }
81
+ }
classes/Twig/Filter/Function.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a function template filter.
14
+ *
15
+ * Use Twig_SimpleFilter instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ class Twig_Filter_Function extends Twig_Filter
21
+ {
22
+ protected $function;
23
+
24
+ public function __construct($function, array $options = array())
25
+ {
26
+ $options['callable'] = $function;
27
+
28
+ parent::__construct($options);
29
+
30
+ $this->function = $function;
31
+ }
32
+
33
+ public function compile()
34
+ {
35
+ return $this->function;
36
+ }
37
+ }
classes/Twig/Filter/Method.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a method template filter.
14
+ *
15
+ * Use Twig_SimpleFilter instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ class Twig_Filter_Method extends Twig_Filter
21
+ {
22
+ protected $extension;
23
+ protected $method;
24
+
25
+ public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
26
+ {
27
+ $options['callable'] = array($extension, $method);
28
+
29
+ parent::__construct($options);
30
+
31
+ $this->extension = $extension;
32
+ $this->method = $method;
33
+ }
34
+
35
+ public function compile()
36
+ {
37
+ return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
38
+ }
39
+ }
classes/Twig/Filter/Node.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template filter as a node.
14
+ *
15
+ * Use Twig_SimpleFilter instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ class Twig_Filter_Node extends Twig_Filter
21
+ {
22
+ protected $class;
23
+
24
+ public function __construct($class, array $options = array())
25
+ {
26
+ parent::__construct($options);
27
+
28
+ $this->class = $class;
29
+ }
30
+
31
+ public function getClass()
32
+ {
33
+ return $this->class;
34
+ }
35
+
36
+ public function compile()
37
+ {
38
+ }
39
+ }
classes/Twig/FilterCallableInterface.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a callable template filter.
14
+ *
15
+ * Use Twig_SimpleFilter instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ interface Twig_FilterCallableInterface
21
+ {
22
+ public function getCallable();
23
+ }
classes/Twig/FilterInterface.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template filter.
14
+ *
15
+ * Use Twig_SimpleFilter instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ interface Twig_FilterInterface
21
+ {
22
+ /**
23
+ * Compiles a filter.
24
+ *
25
+ * @return string The PHP code for the filter
26
+ */
27
+ public function compile();
28
+
29
+ public function needsEnvironment();
30
+
31
+ public function needsContext();
32
+
33
+ public function getSafe(Twig_Node $filterArgs);
34
+
35
+ public function getPreservesSafety();
36
+
37
+ public function getPreEscape();
38
+
39
+ public function setArguments($arguments);
40
+
41
+ public function getArguments();
42
+ }
classes/Twig/Function.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template function.
14
+ *
15
+ * Use Twig_SimpleFunction instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
21
+ {
22
+ protected $options;
23
+ protected $arguments = array();
24
+
25
+ public function __construct(array $options = array())
26
+ {
27
+ $this->options = array_merge(array(
28
+ 'needs_environment' => false,
29
+ 'needs_context' => false,
30
+ 'callable' => null,
31
+ ), $options);
32
+ }
33
+
34
+ public function setArguments($arguments)
35
+ {
36
+ $this->arguments = $arguments;
37
+ }
38
+
39
+ public function getArguments()
40
+ {
41
+ return $this->arguments;
42
+ }
43
+
44
+ public function needsEnvironment()
45
+ {
46
+ return $this->options['needs_environment'];
47
+ }
48
+
49
+ public function needsContext()
50
+ {
51
+ return $this->options['needs_context'];
52
+ }
53
+
54
+ public function getSafe(Twig_Node $functionArgs)
55
+ {
56
+ if (isset($this->options['is_safe'])) {
57
+ return $this->options['is_safe'];
58
+ }
59
+
60
+ if (isset($this->options['is_safe_callback'])) {
61
+ return call_user_func($this->options['is_safe_callback'], $functionArgs);
62
+ }
63
+
64
+ return array();
65
+ }
66
+
67
+ public function getCallable()
68
+ {
69
+ return $this->options['callable'];
70
+ }
71
+ }
classes/Twig/Function/Function.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2010 Arnaud Le Blanc
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a function template function.
15
+ *
16
+ * Use Twig_SimpleFunction instead.
17
+ *
18
+ * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
19
+ * @deprecated since 1.12 (to be removed in 2.0)
20
+ */
21
+ class Twig_Function_Function extends Twig_Function
22
+ {
23
+ protected $function;
24
+
25
+ public function __construct($function, array $options = array())
26
+ {
27
+ $options['callable'] = $function;
28
+
29
+ parent::__construct($options);
30
+
31
+ $this->function = $function;
32
+ }
33
+
34
+ public function compile()
35
+ {
36
+ return $this->function;
37
+ }
38
+ }
classes/Twig/Function/Method.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2010 Arnaud Le Blanc
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a method template function.
15
+ *
16
+ * Use Twig_SimpleFunction instead.
17
+ *
18
+ * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
19
+ * @deprecated since 1.12 (to be removed in 2.0)
20
+ */
21
+ class Twig_Function_Method extends Twig_Function
22
+ {
23
+ protected $extension;
24
+ protected $method;
25
+
26
+ public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
27
+ {
28
+ $options['callable'] = array($extension, $method);
29
+
30
+ parent::__construct($options);
31
+
32
+ $this->extension = $extension;
33
+ $this->method = $method;
34
+ }
35
+
36
+ public function compile()
37
+ {
38
+ return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
39
+ }
40
+ }
classes/Twig/Function/Node.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template function as a node.
14
+ *
15
+ * Use Twig_SimpleFunction instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ class Twig_Function_Node extends Twig_Function
21
+ {
22
+ protected $class;
23
+
24
+ public function __construct($class, array $options = array())
25
+ {
26
+ parent::__construct($options);
27
+
28
+ $this->class = $class;
29
+ }
30
+
31
+ public function getClass()
32
+ {
33
+ return $this->class;
34
+ }
35
+
36
+ public function compile()
37
+ {
38
+ }
39
+ }
classes/Twig/FunctionCallableInterface.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a callable template function.
14
+ *
15
+ * Use Twig_SimpleFunction instead.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ * @deprecated since 1.12 (to be removed in 2.0)
19
+ */
20
+ interface Twig_FunctionCallableInterface
21
+ {
22
+ public function getCallable();
23
+ }
classes/Twig/FunctionInterface.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ * (c) 2010 Arnaud Le Blanc
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a template function.
15
+ *
16
+ * Use Twig_SimpleFunction instead.
17
+ *
18
+ * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
19
+ * @deprecated since 1.12 (to be removed in 2.0)
20
+ */
21
+ interface Twig_FunctionInterface
22
+ {
23
+ /**
24
+ * Compiles a function.
25
+ *
26
+ * @return string The PHP code for the function
27
+ */
28
+ public function compile();
29
+
30
+ public function needsEnvironment();
31
+
32
+ public function needsContext();
33
+
34
+ public function getSafe(Twig_Node $filterArgs);
35
+
36
+ public function setArguments($arguments);
37
+
38
+ public function getArguments();
39
+ }
classes/Twig/Lexer.php ADDED
@@ -0,0 +1,409 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Lexes a template string.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Lexer implements Twig_LexerInterface
19
+ {
20
+ protected $tokens;
21
+ protected $code;
22
+ protected $cursor;
23
+ protected $lineno;
24
+ protected $end;
25
+ protected $state;
26
+ protected $states;
27
+ protected $brackets;
28
+ protected $env;
29
+ protected $filename;
30
+ protected $options;
31
+ protected $regexes;
32
+ protected $position;
33
+ protected $positions;
34
+ protected $currentVarBlockLine;
35
+
36
+ const STATE_DATA = 0;
37
+ const STATE_BLOCK = 1;
38
+ const STATE_VAR = 2;
39
+ const STATE_STRING = 3;
40
+ const STATE_INTERPOLATION = 4;
41
+
42
+ const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
43
+ const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
44
+ const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
45
+ const REGEX_DQ_STRING_DELIM = '/"/A';
46
+ const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
47
+ const PUNCTUATION = '()[]{}?:.,|';
48
+
49
+ public function __construct(Twig_Environment $env, array $options = array())
50
+ {
51
+ $this->env = $env;
52
+
53
+ $this->options = array_merge(array(
54
+ 'tag_comment' => array('{#', '#}'),
55
+ 'tag_block' => array('{%', '%}'),
56
+ 'tag_variable' => array('{{', '}}'),
57
+ 'whitespace_trim' => '-',
58
+ 'interpolation' => array('#{', '}'),
59
+ ), $options);
60
+
61
+ $this->regexes = array(
62
+ 'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
63
+ 'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
64
+ 'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
65
+ 'operator' => $this->getOperatorRegex(),
66
+ 'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
67
+ 'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
68
+ 'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
69
+ 'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
70
+ 'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
71
+ 'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
72
+ );
73
+ }
74
+
75
+ /**
76
+ * {@inheritdoc}
77
+ */
78
+ public function tokenize($code, $filename = null)
79
+ {
80
+ if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
81
+ $mbEncoding = mb_internal_encoding();
82
+ mb_internal_encoding('ASCII');
83
+ } else {
84
+ $mbEncoding = null;
85
+ }
86
+
87
+ $this->code = str_replace(array("\r\n", "\r"), "\n", $code);
88
+ $this->filename = $filename;
89
+ $this->cursor = 0;
90
+ $this->lineno = 1;
91
+ $this->end = strlen($this->code);
92
+ $this->tokens = array();
93
+ $this->state = self::STATE_DATA;
94
+ $this->states = array();
95
+ $this->brackets = array();
96
+ $this->position = -1;
97
+
98
+ // find all token starts in one go
99
+ preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE);
100
+ $this->positions = $matches;
101
+
102
+ while ($this->cursor < $this->end) {
103
+ // dispatch to the lexing functions depending
104
+ // on the current state
105
+ switch ($this->state) {
106
+ case self::STATE_DATA:
107
+ $this->lexData();
108
+ break;
109
+
110
+ case self::STATE_BLOCK:
111
+ $this->lexBlock();
112
+ break;
113
+
114
+ case self::STATE_VAR:
115
+ $this->lexVar();
116
+ break;
117
+
118
+ case self::STATE_STRING:
119
+ $this->lexString();
120
+ break;
121
+
122
+ case self::STATE_INTERPOLATION:
123
+ $this->lexInterpolation();
124
+ break;
125
+ }
126
+ }
127
+
128
+ $this->pushToken(Twig_Token::EOF_TYPE);
129
+
130
+ if (!empty($this->brackets)) {
131
+ list($expect, $lineno) = array_pop($this->brackets);
132
+ throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
133
+ }
134
+
135
+ if ($mbEncoding) {
136
+ mb_internal_encoding($mbEncoding);
137
+ }
138
+
139
+ return new Twig_TokenStream($this->tokens, $this->filename);
140
+ }
141
+
142
+ protected function lexData()
143
+ {
144
+ // if no matches are left we return the rest of the template as simple text token
145
+ if ($this->position == count($this->positions[0]) - 1) {
146
+ $this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor));
147
+ $this->cursor = $this->end;
148
+
149
+ return;
150
+ }
151
+
152
+ // Find the first token after the current cursor
153
+ $position = $this->positions[0][++$this->position];
154
+ while ($position[1] < $this->cursor) {
155
+ if ($this->position == count($this->positions[0]) - 1) {
156
+ return;
157
+ }
158
+ $position = $this->positions[0][++$this->position];
159
+ }
160
+
161
+ // push the template text first
162
+ $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor);
163
+ if (isset($this->positions[2][$this->position][0])) {
164
+ $text = rtrim($text);
165
+ }
166
+ $this->pushToken(Twig_Token::TEXT_TYPE, $text);
167
+ $this->moveCursor($textContent.$position[0]);
168
+
169
+ switch ($this->positions[1][$this->position][0]) {
170
+ case $this->options['tag_comment'][0]:
171
+ $this->lexComment();
172
+ break;
173
+
174
+ case $this->options['tag_block'][0]:
175
+ // raw data?
176
+ if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) {
177
+ $this->moveCursor($match[0]);
178
+ $this->lexRawData($match[1]);
179
+ // {% line \d+ %}
180
+ } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) {
181
+ $this->moveCursor($match[0]);
182
+ $this->lineno = (int) $match[1];
183
+ } else {
184
+ $this->pushToken(Twig_Token::BLOCK_START_TYPE);
185
+ $this->pushState(self::STATE_BLOCK);
186
+ $this->currentVarBlockLine = $this->lineno;
187
+ }
188
+ break;
189
+
190
+ case $this->options['tag_variable'][0]:
191
+ $this->pushToken(Twig_Token::VAR_START_TYPE);
192
+ $this->pushState(self::STATE_VAR);
193
+ $this->currentVarBlockLine = $this->lineno;
194
+ break;
195
+ }
196
+ }
197
+
198
+ protected function lexBlock()
199
+ {
200
+ if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) {
201
+ $this->pushToken(Twig_Token::BLOCK_END_TYPE);
202
+ $this->moveCursor($match[0]);
203
+ $this->popState();
204
+ } else {
205
+ $this->lexExpression();
206
+ }
207
+ }
208
+
209
+ protected function lexVar()
210
+ {
211
+ if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) {
212
+ $this->pushToken(Twig_Token::VAR_END_TYPE);
213
+ $this->moveCursor($match[0]);
214
+ $this->popState();
215
+ } else {
216
+ $this->lexExpression();
217
+ }
218
+ }
219
+
220
+ protected function lexExpression()
221
+ {
222
+ // whitespace
223
+ if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) {
224
+ $this->moveCursor($match[0]);
225
+
226
+ if ($this->cursor >= $this->end) {
227
+ throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->filename);
228
+ }
229
+ }
230
+
231
+ // operators
232
+ if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
233
+ $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0]));
234
+ $this->moveCursor($match[0]);
235
+ }
236
+ // names
237
+ elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) {
238
+ $this->pushToken(Twig_Token::NAME_TYPE, $match[0]);
239
+ $this->moveCursor($match[0]);
240
+ }
241
+ // numbers
242
+ elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) {
243
+ $number = (float) $match[0]; // floats
244
+ if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
245
+ $number = (int) $match[0]; // integers lower than the maximum
246
+ }
247
+ $this->pushToken(Twig_Token::NUMBER_TYPE, $number);
248
+ $this->moveCursor($match[0]);
249
+ }
250
+ // punctuation
251
+ elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) {
252
+ // opening bracket
253
+ if (false !== strpos('([{', $this->code[$this->cursor])) {
254
+ $this->brackets[] = array($this->code[$this->cursor], $this->lineno);
255
+ }
256
+ // closing bracket
257
+ elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
258
+ if (empty($this->brackets)) {
259
+ throw new Twig_Error_Syntax(sprintf('Unexpected "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
260
+ }
261
+
262
+ list($expect, $lineno) = array_pop($this->brackets);
263
+ if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
264
+ throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
265
+ }
266
+ }
267
+
268
+ $this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]);
269
+ ++$this->cursor;
270
+ }
271
+ // strings
272
+ elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) {
273
+ $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)));
274
+ $this->moveCursor($match[0]);
275
+ }
276
+ // opening double quoted string
277
+ elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
278
+ $this->brackets[] = array('"', $this->lineno);
279
+ $this->pushState(self::STATE_STRING);
280
+ $this->moveCursor($match[0]);
281
+ }
282
+ // unlexable
283
+ else {
284
+ throw new Twig_Error_Syntax(sprintf('Unexpected character "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
285
+ }
286
+ }
287
+
288
+ protected function lexRawData($tag)
289
+ {
290
+ if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
291
+ throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename);
292
+ }
293
+
294
+ $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
295
+ $this->moveCursor($text.$match[0][0]);
296
+
297
+ if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) {
298
+ $text = rtrim($text);
299
+ }
300
+
301
+ $this->pushToken(Twig_Token::TEXT_TYPE, $text);
302
+ }
303
+
304
+ protected function lexComment()
305
+ {
306
+ if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
307
+ throw new Twig_Error_Syntax('Unclosed comment', $this->lineno, $this->filename);
308
+ }
309
+
310
+ $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
311
+ }
312
+
313
+ protected function lexString()
314
+ {
315
+ if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) {
316
+ $this->brackets[] = array($this->options['interpolation'][0], $this->lineno);
317
+ $this->pushToken(Twig_Token::INTERPOLATION_START_TYPE);
318
+ $this->moveCursor($match[0]);
319
+ $this->pushState(self::STATE_INTERPOLATION);
320
+
321
+ } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) {
322
+ $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0]));
323
+ $this->moveCursor($match[0]);
324
+
325
+ } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
326
+ list($expect, $lineno) = array_pop($this->brackets);
327
+ if ($this->code[$this->cursor] != '"') {
328
+ throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
329
+ }
330
+
331
+ $this->popState();
332
+ ++$this->cursor;
333
+ }
334
+ }
335
+
336
+ protected function lexInterpolation()
337
+ {
338
+ $bracket = end($this->brackets);
339
+ if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) {
340
+ array_pop($this->brackets);
341
+ $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE);
342
+ $this->moveCursor($match[0]);
343
+ $this->popState();
344
+ } else {
345
+ $this->lexExpression();
346
+ }
347
+ }
348
+
349
+ protected function pushToken($type, $value = '')
350
+ {
351
+ // do not push empty text tokens
352
+ if (Twig_Token::TEXT_TYPE === $type && '' === $value) {
353
+ return;
354
+ }
355
+
356
+ $this->tokens[] = new Twig_Token($type, $value, $this->lineno);
357
+ }
358
+
359
+ protected function moveCursor($text)
360
+ {
361
+ $this->cursor += strlen($text);
362
+ $this->lineno += substr_count($text, "\n");
363
+ }
364
+
365
+ protected function getOperatorRegex()
366
+ {
367
+ $operators = array_merge(
368
+ array('='),
369
+ array_keys($this->env->getUnaryOperators()),
370
+ array_keys($this->env->getBinaryOperators())
371
+ );
372
+
373
+ $operators = array_combine($operators, array_map('strlen', $operators));
374
+ arsort($operators);
375
+
376
+ $regex = array();
377
+ foreach ($operators as $operator => $length) {
378
+ // an operator that ends with a character must be followed by
379
+ // a whitespace or a parenthesis
380
+ if (ctype_alpha($operator[$length - 1])) {
381
+ $r = preg_quote($operator, '/').'(?=[\s()])';
382
+ } else {
383
+ $r = preg_quote($operator, '/');
384
+ }
385
+
386
+ // an operator with a space can be any amount of whitespaces
387
+ $r = preg_replace('/\s+/', '\s+', $r);
388
+
389
+ $regex[] = $r;
390
+ }
391
+
392
+ return '/'.implode('|', $regex).'/A';
393
+ }
394
+
395
+ protected function pushState($state)
396
+ {
397
+ $this->states[] = $this->state;
398
+ $this->state = $state;
399
+ }
400
+
401
+ protected function popState()
402
+ {
403
+ if (0 === count($this->states)) {
404
+ throw new Exception('Cannot pop state without a previous state');
405
+ }
406
+
407
+ $this->state = array_pop($this->states);
408
+ }
409
+ }
classes/Twig/LexerInterface.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface implemented by lexer classes.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ *
17
+ * @deprecated since 1.12 (to be removed in 3.0)
18
+ */
19
+ interface Twig_LexerInterface
20
+ {
21
+ /**
22
+ * Tokenizes a source code.
23
+ *
24
+ * @param string $code The source code
25
+ * @param string $filename A unique identifier for the source code
26
+ *
27
+ * @return Twig_TokenStream A token stream instance
28
+ *
29
+ * @throws Twig_Error_Syntax When the code is syntactically wrong
30
+ */
31
+ public function tokenize($code, $filename = null);
32
+ }
classes/Twig/Loader/Array.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Loads a template from an array.
14
+ *
15
+ * When using this loader with a cache mechanism, you should know that a new cache
16
+ * key is generated each time a template content "changes" (the cache key being the
17
+ * source code of the template). If you don't want to see your cache grows out of
18
+ * control, you need to take care of clearing the old cache file by yourself.
19
+ *
20
+ * @author Fabien Potencier <fabien@symfony.com>
21
+ */
22
+ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
23
+ {
24
+ protected $templates = array();
25
+
26
+ /**
27
+ * Constructor.
28
+ *
29
+ * @param array $templates An array of templates (keys are the names, and values are the source code)
30
+ *
31
+ * @see Twig_Loader
32
+ */
33
+ public function __construct(array $templates)
34
+ {
35
+ $this->templates = $templates;
36
+ }
37
+
38
+ /**
39
+ * Adds or overrides a template.
40
+ *
41
+ * @param string $name The template name
42
+ * @param string $template The template source
43
+ */
44
+ public function setTemplate($name, $template)
45
+ {
46
+ $this->templates[(string) $name] = $template;
47
+ }
48
+
49
+ /**
50
+ * {@inheritdoc}
51
+ */
52
+ public function getSource($name)
53
+ {
54
+ $name = (string) $name;
55
+ if (!isset($this->templates[$name])) {
56
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
57
+ }
58
+
59
+ return $this->templates[$name];
60
+ }
61
+
62
+ /**
63
+ * {@inheritdoc}
64
+ */
65
+ public function exists($name)
66
+ {
67
+ return isset($this->templates[(string) $name]);
68
+ }
69
+
70
+ /**
71
+ * {@inheritdoc}
72
+ */
73
+ public function getCacheKey($name)
74
+ {
75
+ $name = (string) $name;
76
+ if (!isset($this->templates[$name])) {
77
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
78
+ }
79
+
80
+ return $this->templates[$name];
81
+ }
82
+
83
+ /**
84
+ * {@inheritdoc}
85
+ */
86
+ public function isFresh($name, $time)
87
+ {
88
+ $name = (string) $name;
89
+ if (!isset($this->templates[$name])) {
90
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
91
+ }
92
+
93
+ return true;
94
+ }
95
+ }
classes/Twig/Loader/Chain.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Loads templates from other loaders.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
18
+ {
19
+ private $hasSourceCache = array();
20
+ protected $loaders = array();
21
+
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @param Twig_LoaderInterface[] $loaders An array of loader instances
26
+ */
27
+ public function __construct(array $loaders = array())
28
+ {
29
+ foreach ($loaders as $loader) {
30
+ $this->addLoader($loader);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Adds a loader instance.
36
+ *
37
+ * @param Twig_LoaderInterface $loader A Loader instance
38
+ */
39
+ public function addLoader(Twig_LoaderInterface $loader)
40
+ {
41
+ $this->loaders[] = $loader;
42
+ $this->hasSourceCache = array();
43
+ }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getSource($name)
49
+ {
50
+ $exceptions = array();
51
+ foreach ($this->loaders as $loader) {
52
+ if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
53
+ continue;
54
+ }
55
+
56
+ try {
57
+ return $loader->getSource($name);
58
+ } catch (Twig_Error_Loader $e) {
59
+ $exceptions[] = $e->getMessage();
60
+ }
61
+ }
62
+
63
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
64
+ }
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ public function exists($name)
70
+ {
71
+ $name = (string) $name;
72
+
73
+ if (isset($this->hasSourceCache[$name])) {
74
+ return $this->hasSourceCache[$name];
75
+ }
76
+
77
+ foreach ($this->loaders as $loader) {
78
+ if ($loader instanceof Twig_ExistsLoaderInterface) {
79
+ if ($loader->exists($name)) {
80
+ return $this->hasSourceCache[$name] = true;
81
+ }
82
+
83
+ continue;
84
+ }
85
+
86
+ try {
87
+ $loader->getSource($name);
88
+
89
+ return $this->hasSourceCache[$name] = true;
90
+ } catch (Twig_Error_Loader $e) {
91
+ }
92
+ }
93
+
94
+ return $this->hasSourceCache[$name] = false;
95
+ }
96
+
97
+ /**
98
+ * {@inheritdoc}
99
+ */
100
+ public function getCacheKey($name)
101
+ {
102
+ $exceptions = array();
103
+ foreach ($this->loaders as $loader) {
104
+ if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
105
+ continue;
106
+ }
107
+
108
+ try {
109
+ return $loader->getCacheKey($name);
110
+ } catch (Twig_Error_Loader $e) {
111
+ $exceptions[] = get_class($loader).': '.$e->getMessage();
112
+ }
113
+ }
114
+
115
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
116
+ }
117
+
118
+ /**
119
+ * {@inheritdoc}
120
+ */
121
+ public function isFresh($name, $time)
122
+ {
123
+ $exceptions = array();
124
+ foreach ($this->loaders as $loader) {
125
+ if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
126
+ continue;
127
+ }
128
+
129
+ try {
130
+ return $loader->isFresh($name, $time);
131
+ } catch (Twig_Error_Loader $e) {
132
+ $exceptions[] = get_class($loader).': '.$e->getMessage();
133
+ }
134
+ }
135
+
136
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
137
+ }
138
+ }
classes/Twig/Loader/Filesystem.php ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Loads template from the filesystem.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
18
+ {
19
+ /** Identifier of the main namespace. */
20
+ const MAIN_NAMESPACE = '__main__';
21
+
22
+ protected $paths = array();
23
+ protected $cache = array();
24
+
25
+ /**
26
+ * Constructor.
27
+ *
28
+ * @param string|array $paths A path or an array of paths where to look for templates
29
+ */
30
+ public function __construct($paths = array())
31
+ {
32
+ if ($paths) {
33
+ $this->setPaths($paths);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Returns the paths to the templates.
39
+ *
40
+ * @param string $namespace A path namespace
41
+ *
42
+ * @return array The array of paths where to look for templates
43
+ */
44
+ public function getPaths($namespace = self::MAIN_NAMESPACE)
45
+ {
46
+ return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
47
+ }
48
+
49
+ /**
50
+ * Returns the path namespaces.
51
+ *
52
+ * The main namespace is always defined.
53
+ *
54
+ * @return array The array of defined namespaces
55
+ */
56
+ public function getNamespaces()
57
+ {
58
+ return array_keys($this->paths);
59
+ }
60
+
61
+ /**
62
+ * Sets the paths where templates are stored.
63
+ *
64
+ * @param string|array $paths A path or an array of paths where to look for templates
65
+ * @param string $namespace A path namespace
66
+ */
67
+ public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
68
+ {
69
+ if (!is_array($paths)) {
70
+ $paths = array($paths);
71
+ }
72
+
73
+ $this->paths[$namespace] = array();
74
+ foreach ($paths as $path) {
75
+ $this->addPath($path, $namespace);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Adds a path where templates are stored.
81
+ *
82
+ * @param string $path A path where to look for templates
83
+ * @param string $namespace A path name
84
+ *
85
+ * @throws Twig_Error_Loader
86
+ */
87
+ public function addPath($path, $namespace = self::MAIN_NAMESPACE)
88
+ {
89
+ // invalidate the cache
90
+ $this->cache = array();
91
+
92
+ if (!is_dir($path)) {
93
+ throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
94
+ }
95
+
96
+ $this->paths[$namespace][] = rtrim($path, '/\\');
97
+ }
98
+
99
+ /**
100
+ * Prepends a path where templates are stored.
101
+ *
102
+ * @param string $path A path where to look for templates
103
+ * @param string $namespace A path name
104
+ *
105
+ * @throws Twig_Error_Loader
106
+ */
107
+ public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
108
+ {
109
+ // invalidate the cache
110
+ $this->cache = array();
111
+
112
+ if (!is_dir($path)) {
113
+ throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
114
+ }
115
+
116
+ $path = rtrim($path, '/\\');
117
+
118
+ if (!isset($this->paths[$namespace])) {
119
+ $this->paths[$namespace][] = $path;
120
+ } else {
121
+ array_unshift($this->paths[$namespace], $path);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * {@inheritdoc}
127
+ */
128
+ public function getSource($name)
129
+ {
130
+ return file_get_contents($this->findTemplate($name));
131
+ }
132
+
133
+ /**
134
+ * {@inheritdoc}
135
+ */
136
+ public function getCacheKey($name)
137
+ {
138
+ return $this->findTemplate($name);
139
+ }
140
+
141
+ /**
142
+ * {@inheritdoc}
143
+ */
144
+ public function exists($name)
145
+ {
146
+ $name = $this->normalizeName($name);
147
+
148
+ if (isset($this->cache[$name])) {
149
+ return true;
150
+ }
151
+
152
+ try {
153
+ $this->findTemplate($name);
154
+
155
+ return true;
156
+ } catch (Twig_Error_Loader $exception) {
157
+ return false;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * {@inheritdoc}
163
+ */
164
+ public function isFresh($name, $time)
165
+ {
166
+ return filemtime($this->findTemplate($name)) <= $time;
167
+ }
168
+
169
+ protected function findTemplate($name)
170
+ {
171
+ $name = $this->normalizeName($name);
172
+
173
+ if (isset($this->cache[$name])) {
174
+ return $this->cache[$name];
175
+ }
176
+
177
+ $this->validateName($name);
178
+
179
+ list($namespace, $shortname) = $this->parseName($name);
180
+
181
+ if (!isset($this->paths[$namespace])) {
182
+ throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
183
+ }
184
+
185
+ foreach ($this->paths[$namespace] as $path) {
186
+ if (is_file($path.'/'.$shortname)) {
187
+ return $this->cache[$name] = $path.'/'.$shortname;
188
+ }
189
+ }
190
+
191
+ throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
192
+ }
193
+
194
+ protected function parseName($name, $default = self::MAIN_NAMESPACE)
195
+ {
196
+ if (isset($name[0]) && '@' == $name[0]) {
197
+ if (false === $pos = strpos($name, '/')) {
198
+ throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
199
+ }
200
+
201
+ $namespace = substr($name, 1, $pos - 1);
202
+ $shortname = substr($name, $pos + 1);
203
+
204
+ return array($namespace, $shortname);
205
+ }
206
+
207
+ return array($default, $name);
208
+ }
209
+
210
+ protected function normalizeName($name)
211
+ {
212
+ return preg_replace('#/{2,}#', '/', strtr((string) $name, '\\', '/'));
213
+ }
214
+
215
+ protected function validateName($name)
216
+ {
217
+ if (false !== strpos($name, "\0")) {
218
+ throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
219
+ }
220
+
221
+ $name = ltrim($name, '/');
222
+ $parts = explode('/', $name);
223
+ $level = 0;
224
+ foreach ($parts as $part) {
225
+ if ('..' === $part) {
226
+ --$level;
227
+ } elseif ('.' !== $part) {
228
+ ++$level;
229
+ }
230
+
231
+ if ($level < 0) {
232
+ throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
233
+ }
234
+ }
235
+ }
236
+ }
classes/Twig/Loader/String.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Loads a template from a string.
14
+ *
15
+ * This loader should only be used for unit testing as it has many limitations
16
+ * (for instance, the include or extends tag does not make any sense for a string
17
+ * loader).
18
+ *
19
+ * When using this loader with a cache mechanism, you should know that a new cache
20
+ * key is generated each time a template content "changes" (the cache key being the
21
+ * source code of the template). If you don't want to see your cache grows out of
22
+ * control, you need to take care of clearing the old cache file by yourself.
23
+ *
24
+ * @author Fabien Potencier <fabien@symfony.com>
25
+ */
26
+ class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
27
+ {
28
+ /**
29
+ * {@inheritdoc}
30
+ */
31
+ public function getSource($name)
32
+ {
33
+ return $name;
34
+ }
35
+
36
+ /**
37
+ * {@inheritdoc}
38
+ */
39
+ public function exists($name)
40
+ {
41
+ return true;
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ public function getCacheKey($name)
48
+ {
49
+ return $name;
50
+ }
51
+
52
+ /**
53
+ * {@inheritdoc}
54
+ */
55
+ public function isFresh($name, $time)
56
+ {
57
+ return true;
58
+ }
59
+ }
classes/Twig/LoaderInterface.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface all loaders must implement.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ interface Twig_LoaderInterface
18
+ {
19
+ /**
20
+ * Gets the source code of a template, given its name.
21
+ *
22
+ * @param string $name The name of the template to load
23
+ *
24
+ * @return string The template source code
25
+ *
26
+ * @throws Twig_Error_Loader When $name is not found
27
+ */
28
+ public function getSource($name);
29
+
30
+ /**
31
+ * Gets the cache key to use for the cache for a given template name.
32
+ *
33
+ * @param string $name The name of the template to load
34
+ *
35
+ * @return string The cache key
36
+ *
37
+ * @throws Twig_Error_Loader When $name is not found
38
+ */
39
+ public function getCacheKey($name);
40
+
41
+ /**
42
+ * Returns true if the template is still fresh.
43
+ *
44
+ * @param string $name The template name
45
+ * @param timestamp $time The last modification time of the cached template
46
+ *
47
+ * @return bool true if the template is fresh, false otherwise
48
+ *
49
+ * @throws Twig_Error_Loader When $name is not found
50
+ */
51
+ public function isFresh($name, $time);
52
+ }
classes/Twig/Markup.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Marks a content as safe.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Markup implements Countable
18
+ {
19
+ protected $content;
20
+ protected $charset;
21
+
22
+ public function __construct($content, $charset)
23
+ {
24
+ $this->content = (string) $content;
25
+ $this->charset = $charset;
26
+ }
27
+
28
+ public function __toString()
29
+ {
30
+ return $this->content;
31
+ }
32
+
33
+ public function count()
34
+ {
35
+ return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content);
36
+ }
37
+ }
classes/Twig/Node.php ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a node in the AST.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node implements Twig_NodeInterface
19
+ {
20
+ protected $nodes;
21
+ protected $attributes;
22
+ protected $lineno;
23
+ protected $tag;
24
+
25
+ /**
26
+ * Constructor.
27
+ *
28
+ * The nodes are automatically made available as properties ($this->node).
29
+ * The attributes are automatically made available as array items ($this['name']).
30
+ *
31
+ * @param array $nodes An array of named nodes
32
+ * @param array $attributes An array of attributes (should not be nodes)
33
+ * @param int $lineno The line number
34
+ * @param string $tag The tag name associated with the Node
35
+ */
36
+ public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null)
37
+ {
38
+ $this->nodes = $nodes;
39
+ $this->attributes = $attributes;
40
+ $this->lineno = $lineno;
41
+ $this->tag = $tag;
42
+ }
43
+
44
+ public function __toString()
45
+ {
46
+ $attributes = array();
47
+ foreach ($this->attributes as $name => $value) {
48
+ $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
49
+ }
50
+
51
+ $repr = array(get_class($this).'('.implode(', ', $attributes));
52
+
53
+ if (count($this->nodes)) {
54
+ foreach ($this->nodes as $name => $node) {
55
+ $len = strlen($name) + 4;
56
+ $noderepr = array();
57
+ foreach (explode("\n", (string) $node) as $line) {
58
+ $noderepr[] = str_repeat(' ', $len).$line;
59
+ }
60
+
61
+ $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr)));
62
+ }
63
+
64
+ $repr[] = ')';
65
+ } else {
66
+ $repr[0] .= ')';
67
+ }
68
+
69
+ return implode("\n", $repr);
70
+ }
71
+
72
+ public function toXml($asDom = false)
73
+ {
74
+ $dom = new DOMDocument('1.0', 'UTF-8');
75
+ $dom->formatOutput = true;
76
+ $dom->appendChild($xml = $dom->createElement('twig'));
77
+
78
+ $xml->appendChild($node = $dom->createElement('node'));
79
+ $node->setAttribute('class', get_class($this));
80
+
81
+ foreach ($this->attributes as $name => $value) {
82
+ $node->appendChild($attribute = $dom->createElement('attribute'));
83
+ $attribute->setAttribute('name', $name);
84
+ $attribute->appendChild($dom->createTextNode($value));
85
+ }
86
+
87
+ foreach ($this->nodes as $name => $n) {
88
+ if (null === $n) {
89
+ continue;
90
+ }
91
+
92
+ $child = $n->toXml(true)->getElementsByTagName('node')->item(0);
93
+ $child = $dom->importNode($child, true);
94
+ $child->setAttribute('name', $name);
95
+
96
+ $node->appendChild($child);
97
+ }
98
+
99
+ return $asDom ? $dom : $dom->saveXml();
100
+ }
101
+
102
+ public function compile(Twig_Compiler $compiler)
103
+ {
104
+ foreach ($this->nodes as $node) {
105
+ $node->compile($compiler);
106
+ }
107
+ }
108
+
109
+ public function getLine()
110
+ {
111
+ return $this->lineno;
112
+ }
113
+
114
+ public function getNodeTag()
115
+ {
116
+ return $this->tag;
117
+ }
118
+
119
+ /**
120
+ * Returns true if the attribute is defined.
121
+ *
122
+ * @param string The attribute name
123
+ *
124
+ * @return bool true if the attribute is defined, false otherwise
125
+ */
126
+ public function hasAttribute($name)
127
+ {
128
+ return array_key_exists($name, $this->attributes);
129
+ }
130
+
131
+ /**
132
+ * Gets an attribute.
133
+ *
134
+ * @param string The attribute name
135
+ *
136
+ * @return mixed The attribute value
137
+ */
138
+ public function getAttribute($name)
139
+ {
140
+ if (!array_key_exists($name, $this->attributes)) {
141
+ throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
142
+ }
143
+
144
+ return $this->attributes[$name];
145
+ }
146
+
147
+ /**
148
+ * Sets an attribute.
149
+ *
150
+ * @param string The attribute name
151
+ * @param mixed The attribute value
152
+ */
153
+ public function setAttribute($name, $value)
154
+ {
155
+ $this->attributes[$name] = $value;
156
+ }
157
+
158
+ /**
159
+ * Removes an attribute.
160
+ *
161
+ * @param string The attribute name
162
+ */
163
+ public function removeAttribute($name)
164
+ {
165
+ unset($this->attributes[$name]);
166
+ }
167
+
168
+ /**
169
+ * Returns true if the node with the given identifier exists.
170
+ *
171
+ * @param string The node name
172
+ *
173
+ * @return bool true if the node with the given name exists, false otherwise
174
+ */
175
+ public function hasNode($name)
176
+ {
177
+ return array_key_exists($name, $this->nodes);
178
+ }
179
+
180
+ /**
181
+ * Gets a node by name.
182
+ *
183
+ * @param string The node name
184
+ *
185
+ * @return Twig_Node A Twig_Node instance
186
+ */
187
+ public function getNode($name)
188
+ {
189
+ if (!array_key_exists($name, $this->nodes)) {
190
+ throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
191
+ }
192
+
193
+ return $this->nodes[$name];
194
+ }
195
+
196
+ /**
197
+ * Sets a node.
198
+ *
199
+ * @param string The node name
200
+ * @param Twig_Node A Twig_Node instance
201
+ */
202
+ public function setNode($name, $node = null)
203
+ {
204
+ $this->nodes[$name] = $node;
205
+ }
206
+
207
+ /**
208
+ * Removes a node by name.
209
+ *
210
+ * @param string The node name
211
+ */
212
+ public function removeNode($name)
213
+ {
214
+ unset($this->nodes[$name]);
215
+ }
216
+
217
+ public function count()
218
+ {
219
+ return count($this->nodes);
220
+ }
221
+
222
+ public function getIterator()
223
+ {
224
+ return new ArrayIterator($this->nodes);
225
+ }
226
+ }
classes/Twig/Node/AutoEscape.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents an autoescape node.
14
+ *
15
+ * The value is the escaping strategy (can be html, js, ...)
16
+ *
17
+ * The true value is equivalent to html.
18
+ *
19
+ * If autoescaping is disabled, then the value is false.
20
+ *
21
+ * @author Fabien Potencier <fabien@symfony.com>
22
+ */
23
+ class Twig_Node_AutoEscape extends Twig_Node
24
+ {
25
+ public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
26
+ {
27
+ parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
28
+ }
29
+
30
+ /**
31
+ * Compiles the node to PHP.
32
+ *
33
+ * @param Twig_Compiler A Twig_Compiler instance
34
+ */
35
+ public function compile(Twig_Compiler $compiler)
36
+ {
37
+ $compiler->subcompile($this->getNode('body'));
38
+ }
39
+ }
classes/Twig/Node/Block.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a block node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Block extends Twig_Node
19
+ {
20
+ public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ $compiler
33
+ ->addDebugInfo($this)
34
+ ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n")
35
+ ->indent()
36
+ ;
37
+
38
+ $compiler
39
+ ->subcompile($this->getNode('body'))
40
+ ->outdent()
41
+ ->write("}\n\n")
42
+ ;
43
+ }
44
+ }
classes/Twig/Node/BlockReference.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a block call node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
19
+ {
20
+ public function __construct($name, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array(), array('name' => $name), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ $compiler
33
+ ->addDebugInfo($this)
34
+ ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
35
+ ;
36
+ }
37
+ }
classes/Twig/Node/Body.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a body node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Body extends Twig_Node
18
+ {
19
+ }
classes/Twig/Node/Do.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a do node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Do extends Twig_Node
18
+ {
19
+ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
20
+ {
21
+ parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ $compiler
32
+ ->addDebugInfo($this)
33
+ ->write('')
34
+ ->subcompile($this->getNode('expr'))
35
+ ->raw(";\n")
36
+ ;
37
+ }
38
+ }
classes/Twig/Node/Embed.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents an embed node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Embed extends Twig_Node_Include
18
+ {
19
+ // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
20
+ public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
23
+
24
+ $this->setAttribute('filename', $filename);
25
+ $this->setAttribute('index', $index);
26
+ }
27
+
28
+ protected function addGetTemplate(Twig_Compiler $compiler)
29
+ {
30
+ $compiler
31
+ ->write("\$this->env->loadTemplate(")
32
+ ->string($this->getAttribute('filename'))
33
+ ->raw(', ')
34
+ ->string($this->getAttribute('index'))
35
+ ->raw(")")
36
+ ;
37
+ }
38
+ }
classes/Twig/Node/Expression.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Abstract class for all nodes that represents an expression.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ abstract class Twig_Node_Expression extends Twig_Node
19
+ {
20
+ }
classes/Twig/Node/Expression/Array.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Array extends Twig_Node_Expression
12
+ {
13
+ protected $index;
14
+
15
+ public function __construct(array $elements, $lineno)
16
+ {
17
+ parent::__construct($elements, array(), $lineno);
18
+
19
+ $this->index = -1;
20
+ foreach ($this->getKeyValuePairs() as $pair) {
21
+ if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
22
+ $this->index = $pair['key']->getAttribute('value');
23
+ }
24
+ }
25
+ }
26
+
27
+ public function getKeyValuePairs()
28
+ {
29
+ $pairs = array();
30
+
31
+ foreach (array_chunk($this->nodes, 2) as $pair) {
32
+ $pairs[] = array(
33
+ 'key' => $pair[0],
34
+ 'value' => $pair[1],
35
+ );
36
+ }
37
+
38
+ return $pairs;
39
+ }
40
+
41
+ public function hasElement(Twig_Node_Expression $key)
42
+ {
43
+ foreach ($this->getKeyValuePairs() as $pair) {
44
+ // we compare the string representation of the keys
45
+ // to avoid comparing the line numbers which are not relevant here.
46
+ if ((string) $key == (string) $pair['key']) {
47
+ return true;
48
+ }
49
+ }
50
+
51
+ return false;
52
+ }
53
+
54
+ public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
55
+ {
56
+ if (null === $key) {
57
+ $key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine());
58
+ }
59
+
60
+ array_push($this->nodes, $key, $value);
61
+ }
62
+
63
+ /**
64
+ * Compiles the node to PHP.
65
+ *
66
+ * @param Twig_Compiler A Twig_Compiler instance
67
+ */
68
+ public function compile(Twig_Compiler $compiler)
69
+ {
70
+ $compiler->raw('array(');
71
+ $first = true;
72
+ foreach ($this->getKeyValuePairs() as $pair) {
73
+ if (!$first) {
74
+ $compiler->raw(', ');
75
+ }
76
+ $first = false;
77
+
78
+ $compiler
79
+ ->subcompile($pair['key'])
80
+ ->raw(' => ')
81
+ ->subcompile($pair['value'])
82
+ ;
83
+ }
84
+ $compiler->raw(')');
85
+ }
86
+ }
classes/Twig/Node/Expression/AssignName.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
14
+ {
15
+ /**
16
+ * Compiles the node to PHP.
17
+ *
18
+ * @param Twig_Compiler A Twig_Compiler instance
19
+ */
20
+ public function compile(Twig_Compiler $compiler)
21
+ {
22
+ $compiler
23
+ ->raw('$context[')
24
+ ->string($this->getAttribute('name'))
25
+ ->raw(']')
26
+ ;
27
+ }
28
+ }
classes/Twig/Node/Expression/Binary.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
13
+ {
14
+ public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
15
+ {
16
+ parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
17
+ }
18
+
19
+ /**
20
+ * Compiles the node to PHP.
21
+ *
22
+ * @param Twig_Compiler A Twig_Compiler instance
23
+ */
24
+ public function compile(Twig_Compiler $compiler)
25
+ {
26
+ $compiler
27
+ ->raw('(')
28
+ ->subcompile($this->getNode('left'))
29
+ ->raw(' ')
30
+ ;
31
+ $this->operator($compiler);
32
+ $compiler
33
+ ->raw(' ')
34
+ ->subcompile($this->getNode('right'))
35
+ ->raw(')')
36
+ ;
37
+ }
38
+
39
+ abstract public function operator(Twig_Compiler $compiler);
40
+ }
classes/Twig/Node/Expression/Binary/Add.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('+');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/And.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('&&');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/BitwiseAnd.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('&');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/BitwiseOr.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('|');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/BitwiseXor.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('^');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/Concat.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('.');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/Div.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('/');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/EndsWith.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2013 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
12
+ {
13
+ public function compile(Twig_Compiler $compiler)
14
+ {
15
+ $compiler
16
+ ->raw('(0 === substr_compare(')
17
+ ->subcompile($this->getNode('left'))
18
+ ->raw(', ')
19
+ ->subcompile($this->getNode('right'))
20
+ ->raw(', -strlen(')
21
+ ->subcompile($this->getNode('right'))
22
+ ->raw(')))')
23
+ ;
24
+ }
25
+
26
+ public function operator(Twig_Compiler $compiler)
27
+ {
28
+ return $compiler->raw('');
29
+ }
30
+ }
classes/Twig/Node/Expression/Binary/Equal.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
12
+ {
13
+ public function operator(Twig_Compiler $compiler)
14
+ {
15
+ return $compiler->raw('==');
16
+ }
17
+ }
classes/Twig/Node/Expression/Binary/FloorDiv.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
12
+ {
13
+ /**
14
+ * Compiles the node to PHP.
15
+ *
16
+ * @param Twig_Compiler A Twig_Compiler instance
17
+ */
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $compiler->raw('intval(floor(');
21
+ parent::compile($compiler);
22
+ $compiler->raw('))');
23
+ }
24
+
25
+ public function operator(Twig_Compiler $compiler)
26
+ {
27
+ return $compiler->raw('/');
28
+ }
29
+ }
classes/Twig/Node/Expression/Binary/Greater.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
12
+ {
13
+ public function operator(Twig_Compiler $compiler)
14
+ {
15
+ return $compiler->raw('>');
16
+ }
17
+ }
classes/Twig/Node/Expression/Binary/GreaterEqual.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary
12
+ {
13
+ public function operator(Twig_Compiler $compiler)
14
+ {
15
+ return $compiler->raw('>=');
16
+ }
17
+ }
classes/Twig/Node/Expression/Binary/In.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
12
+ {
13
+ /**
14
+ * Compiles the node to PHP.
15
+ *
16
+ * @param Twig_Compiler A Twig_Compiler instance
17
+ */
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $compiler
21
+ ->raw('twig_in_filter(')
22
+ ->subcompile($this->getNode('left'))
23
+ ->raw(', ')
24
+ ->subcompile($this->getNode('right'))
25
+ ->raw(')')
26
+ ;
27
+ }
28
+
29
+ public function operator(Twig_Compiler $compiler)
30
+ {
31
+ return $compiler->raw('in');
32
+ }
33
+ }
classes/Twig/Node/Expression/Binary/Less.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
12
+ {
13
+ public function operator(Twig_Compiler $compiler)
14
+ {
15
+ return $compiler->raw('<');
16
+ }
17
+ }
classes/Twig/Node/Expression/Binary/LessEqual.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
12
+ {
13
+ public function operator(Twig_Compiler $compiler)
14
+ {
15
+ return $compiler->raw('<=');
16
+ }
17
+ }
classes/Twig/Node/Expression/Binary/Matches.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2013 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary
12
+ {
13
+ public function compile(Twig_Compiler $compiler)
14
+ {
15
+ $compiler
16
+ ->raw('preg_match(')
17
+ ->subcompile($this->getNode('right'))
18
+ ->raw(', ')
19
+ ->subcompile($this->getNode('left'))
20
+ ->raw(')')
21
+ ;
22
+ }
23
+
24
+ public function operator(Twig_Compiler $compiler)
25
+ {
26
+ return $compiler->raw('');
27
+ }
28
+ }
classes/Twig/Node/Expression/Binary/Mod.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('%');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/Mul.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('*');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/NotEqual.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
12
+ {
13
+ public function operator(Twig_Compiler $compiler)
14
+ {
15
+ return $compiler->raw('!=');
16
+ }
17
+ }
classes/Twig/Node/Expression/Binary/NotIn.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
12
+ {
13
+ /**
14
+ * Compiles the node to PHP.
15
+ *
16
+ * @param Twig_Compiler A Twig_Compiler instance
17
+ */
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $compiler
21
+ ->raw('!twig_in_filter(')
22
+ ->subcompile($this->getNode('left'))
23
+ ->raw(', ')
24
+ ->subcompile($this->getNode('right'))
25
+ ->raw(')')
26
+ ;
27
+ }
28
+
29
+ public function operator(Twig_Compiler $compiler)
30
+ {
31
+ return $compiler->raw('not in');
32
+ }
33
+ }
classes/Twig/Node/Expression/Binary/Or.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('||');
17
+ }
18
+ }
classes/Twig/Node/Expression/Binary/Power.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
12
+ {
13
+ /**
14
+ * Compiles the node to PHP.
15
+ *
16
+ * @param Twig_Compiler A Twig_Compiler instance
17
+ */
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $compiler
21
+ ->raw('pow(')
22
+ ->subcompile($this->getNode('left'))
23
+ ->raw(', ')
24
+ ->subcompile($this->getNode('right'))
25
+ ->raw(')')
26
+ ;
27
+ }
28
+
29
+ public function operator(Twig_Compiler $compiler)
30
+ {
31
+ return $compiler->raw('**');
32
+ }
33
+ }
classes/Twig/Node/Expression/Binary/Range.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
12
+ {
13
+ /**
14
+ * Compiles the node to PHP.
15
+ *
16
+ * @param Twig_Compiler A Twig_Compiler instance
17
+ */
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $compiler
21
+ ->raw('range(')
22
+ ->subcompile($this->getNode('left'))
23
+ ->raw(', ')
24
+ ->subcompile($this->getNode('right'))
25
+ ->raw(')')
26
+ ;
27
+ }
28
+
29
+ public function operator(Twig_Compiler $compiler)
30
+ {
31
+ return $compiler->raw('..');
32
+ }
33
+ }
classes/Twig/Node/Expression/Binary/StartsWith.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2013 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
12
+ {
13
+ public function compile(Twig_Compiler $compiler)
14
+ {
15
+ $compiler
16
+ ->raw('(0 === strpos(')
17
+ ->subcompile($this->getNode('left'))
18
+ ->raw(', ')
19
+ ->subcompile($this->getNode('right'))
20
+ ->raw('))')
21
+ ;
22
+ }
23
+
24
+ public function operator(Twig_Compiler $compiler)
25
+ {
26
+ return $compiler->raw('');
27
+ }
28
+ }
classes/Twig/Node/Expression/Binary/Sub.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ return $compiler->raw('-');
17
+ }
18
+ }
classes/Twig/Node/Expression/BlockReference.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a block call node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
19
+ {
20
+ public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ if ($this->getAttribute('as_string')) {
33
+ $compiler->raw('(string) ');
34
+ }
35
+
36
+ if ($this->getAttribute('output')) {
37
+ $compiler
38
+ ->addDebugInfo($this)
39
+ ->write("\$this->displayBlock(")
40
+ ->subcompile($this->getNode('name'))
41
+ ->raw(", \$context, \$blocks);\n")
42
+ ;
43
+ } else {
44
+ $compiler
45
+ ->raw("\$this->renderBlock(")
46
+ ->subcompile($this->getNode('name'))
47
+ ->raw(", \$context, \$blocks)")
48
+ ;
49
+ }
50
+ }
51
+ }
classes/Twig/Node/Expression/Call.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
12
+ {
13
+ protected function compileCallable(Twig_Compiler $compiler)
14
+ {
15
+ $closingParenthesis = false;
16
+ if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
17
+ if (is_string($callable)) {
18
+ $compiler->raw($callable);
19
+ } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
20
+ $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
21
+ } else {
22
+ $type = ucfirst($this->getAttribute('type'));
23
+ $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
24
+ $closingParenthesis = true;
25
+ }
26
+ } else {
27
+ $compiler->raw($this->getAttribute('thing')->compile());
28
+ }
29
+
30
+ $this->compileArguments($compiler);
31
+
32
+ if ($closingParenthesis) {
33
+ $compiler->raw(')');
34
+ }
35
+ }
36
+
37
+ protected function compileArguments(Twig_Compiler $compiler)
38
+ {
39
+ $compiler->raw('(');
40
+
41
+ $first = true;
42
+
43
+ if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
44
+ $compiler->raw('$this->env');
45
+ $first = false;
46
+ }
47
+
48
+ if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
49
+ if (!$first) {
50
+ $compiler->raw(', ');
51
+ }
52
+ $compiler->raw('$context');
53
+ $first = false;
54
+ }
55
+
56
+ if ($this->hasAttribute('arguments')) {
57
+ foreach ($this->getAttribute('arguments') as $argument) {
58
+ if (!$first) {
59
+ $compiler->raw(', ');
60
+ }
61
+ $compiler->string($argument);
62
+ $first = false;
63
+ }
64
+ }
65
+
66
+ if ($this->hasNode('node')) {
67
+ if (!$first) {
68
+ $compiler->raw(', ');
69
+ }
70
+ $compiler->subcompile($this->getNode('node'));
71
+ $first = false;
72
+ }
73
+
74
+ if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
75
+ $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
76
+
77
+ $arguments = $this->getArguments($callable, $this->getNode('arguments'));
78
+
79
+ foreach ($arguments as $node) {
80
+ if (!$first) {
81
+ $compiler->raw(', ');
82
+ }
83
+ $compiler->subcompile($node);
84
+ $first = false;
85
+ }
86
+ }
87
+
88
+ $compiler->raw(')');
89
+ }
90
+
91
+ protected function getArguments($callable, $arguments)
92
+ {
93
+ $parameters = array();
94
+ $named = false;
95
+ foreach ($arguments as $name => $node) {
96
+ if (!is_int($name)) {
97
+ $named = true;
98
+ $name = $this->normalizeName($name);
99
+ } elseif ($named) {
100
+ throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
101
+ }
102
+
103
+ $parameters[$name] = $node;
104
+ }
105
+
106
+ if (!$named) {
107
+ return $parameters;
108
+ }
109
+
110
+ if (!$callable) {
111
+ throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
112
+ }
113
+
114
+ // manage named arguments
115
+ if (is_array($callable)) {
116
+ $r = new ReflectionMethod($callable[0], $callable[1]);
117
+ } elseif (is_object($callable) && !$callable instanceof Closure) {
118
+ $r = new ReflectionObject($callable);
119
+ $r = $r->getMethod('__invoke');
120
+ } else {
121
+ $r = new ReflectionFunction($callable);
122
+ }
123
+
124
+ $definition = $r->getParameters();
125
+ if ($this->hasNode('node')) {
126
+ array_shift($definition);
127
+ }
128
+ if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
129
+ array_shift($definition);
130
+ }
131
+ if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
132
+ array_shift($definition);
133
+ }
134
+ if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
135
+ foreach ($this->getAttribute('arguments') as $argument) {
136
+ array_shift($definition);
137
+ }
138
+ }
139
+
140
+ $arguments = array();
141
+ $pos = 0;
142
+ foreach ($definition as $param) {
143
+ $name = $this->normalizeName($param->name);
144
+
145
+ if (array_key_exists($name, $parameters)) {
146
+ if (array_key_exists($pos, $parameters)) {
147
+ throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
148
+ }
149
+
150
+ $arguments[] = $parameters[$name];
151
+ unset($parameters[$name]);
152
+ } elseif (array_key_exists($pos, $parameters)) {
153
+ $arguments[] = $parameters[$pos];
154
+ unset($parameters[$pos]);
155
+ ++$pos;
156
+ } elseif ($param->isDefaultValueAvailable()) {
157
+ $arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
158
+ } elseif ($param->isOptional()) {
159
+ break;
160
+ } else {
161
+ throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
162
+ }
163
+ }
164
+
165
+ if (!empty($parameters)) {
166
+ throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name')));
167
+ }
168
+
169
+ return $arguments;
170
+ }
171
+
172
+ protected function normalizeName($name)
173
+ {
174
+ return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
175
+ }
176
+ }
classes/Twig/Node/Expression/Conditional.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Conditional extends Twig_Node_Expression
13
+ {
14
+ public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
15
+ {
16
+ parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno);
17
+ }
18
+
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ $compiler
22
+ ->raw('((')
23
+ ->subcompile($this->getNode('expr1'))
24
+ ->raw(') ? (')
25
+ ->subcompile($this->getNode('expr2'))
26
+ ->raw(') : (')
27
+ ->subcompile($this->getNode('expr3'))
28
+ ->raw('))')
29
+ ;
30
+ }
31
+ }
classes/Twig/Node/Expression/Constant.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Constant extends Twig_Node_Expression
13
+ {
14
+ public function __construct($value, $lineno)
15
+ {
16
+ parent::__construct(array(), array('value' => $value), $lineno);
17
+ }
18
+
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ $compiler->repr($this->getAttribute('value'));
22
+ }
23
+ }
classes/Twig/Node/Expression/ExtensionReference.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents an extension call node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
18
+ {
19
+ public function __construct($name, $lineno, $tag = null)
20
+ {
21
+ parent::__construct(array(), array('name' => $name), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
32
+ }
33
+ }
classes/Twig/Node/Expression/Filter.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
13
+ {
14
+ public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
15
+ {
16
+ parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
17
+ }
18
+
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ $name = $this->getNode('filter')->getAttribute('value');
22
+ $filter = $compiler->getEnvironment()->getFilter($name);
23
+
24
+ $this->setAttribute('name', $name);
25
+ $this->setAttribute('type', 'filter');
26
+ $this->setAttribute('thing', $filter);
27
+ $this->setAttribute('needs_environment', $filter->needsEnvironment());
28
+ $this->setAttribute('needs_context', $filter->needsContext());
29
+ $this->setAttribute('arguments', $filter->getArguments());
30
+ if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
31
+ $this->setAttribute('callable', $filter->getCallable());
32
+ }
33
+
34
+ $this->compileCallable($compiler);
35
+ }
36
+ }
classes/Twig/Node/Expression/Filter/Default.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Returns the value or the default value when it is undefined or empty.
14
+ *
15
+ * <pre>
16
+ * {{ var.foo|default('foo item on var is not defined') }}
17
+ * </pre>
18
+ *
19
+ * @author Fabien Potencier <fabien@symfony.com>
20
+ */
21
+ class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
22
+ {
23
+ public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
24
+ {
25
+ $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine());
26
+
27
+ if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
28
+ $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine());
29
+ $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine());
30
+
31
+ $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine());
32
+ } else {
33
+ $node = $default;
34
+ }
35
+
36
+ parent::__construct($node, $filterName, $arguments, $lineno, $tag);
37
+ }
38
+
39
+ public function compile(Twig_Compiler $compiler)
40
+ {
41
+ $compiler->subcompile($this->getNode('node'));
42
+ }
43
+ }
classes/Twig/Node/Expression/Function.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
12
+ {
13
+ public function __construct($name, Twig_NodeInterface $arguments, $lineno)
14
+ {
15
+ parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno);
16
+ }
17
+
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $name = $this->getAttribute('name');
21
+ $function = $compiler->getEnvironment()->getFunction($name);
22
+
23
+ $this->setAttribute('name', $name);
24
+ $this->setAttribute('type', 'function');
25
+ $this->setAttribute('thing', $function);
26
+ $this->setAttribute('needs_environment', $function->needsEnvironment());
27
+ $this->setAttribute('needs_context', $function->needsContext());
28
+ $this->setAttribute('arguments', $function->getArguments());
29
+ if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
30
+ $this->setAttribute('callable', $function->getCallable());
31
+ }
32
+
33
+ $this->compileCallable($compiler);
34
+ }
35
+ }
classes/Twig/Node/Expression/GetAttr.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
13
+ {
14
+ public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
15
+ {
16
+ parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
17
+ }
18
+
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
22
+ $compiler->raw('twig_template_get_attributes($this, ');
23
+ } else {
24
+ $compiler->raw('$this->getAttribute(');
25
+ }
26
+
27
+ if ($this->getAttribute('ignore_strict_check')) {
28
+ $this->getNode('node')->setAttribute('ignore_strict_check', true);
29
+ }
30
+
31
+ $compiler->subcompile($this->getNode('node'));
32
+
33
+ $compiler->raw(', ')->subcompile($this->getNode('attribute'));
34
+
35
+ if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
36
+ $compiler->raw(', ')->subcompile($this->getNode('arguments'));
37
+
38
+ if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
39
+ $compiler->raw(', ')->repr($this->getAttribute('type'));
40
+ }
41
+
42
+ if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
43
+ $compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false'));
44
+ }
45
+
46
+ if ($this->getAttribute('ignore_strict_check')) {
47
+ $compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false'));
48
+ }
49
+ }
50
+
51
+ $compiler->raw(')');
52
+ }
53
+ }
classes/Twig/Node/Expression/MethodCall.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
12
+ {
13
+ public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
14
+ {
15
+ parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno);
16
+
17
+ if ($node instanceof Twig_Node_Expression_Name) {
18
+ $node->setAttribute('always_defined', true);
19
+ }
20
+ }
21
+
22
+ public function compile(Twig_Compiler $compiler)
23
+ {
24
+ $compiler
25
+ ->subcompile($this->getNode('node'))
26
+ ->raw('->')
27
+ ->raw($this->getAttribute('method'))
28
+ ->raw('(')
29
+ ;
30
+ $first = true;
31
+ foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
32
+ if (!$first) {
33
+ $compiler->raw(', ');
34
+ }
35
+ $first = false;
36
+
37
+ $compiler->subcompile($pair['value']);
38
+ }
39
+ $compiler->raw(')');
40
+ }
41
+ }
classes/Twig/Node/Expression/Name.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Name extends Twig_Node_Expression
13
+ {
14
+ protected $specialVars = array(
15
+ '_self' => '$this',
16
+ '_context' => '$context',
17
+ '_charset' => '$this->env->getCharset()',
18
+ );
19
+
20
+ public function __construct($name, $lineno)
21
+ {
22
+ parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno);
23
+ }
24
+
25
+ public function compile(Twig_Compiler $compiler)
26
+ {
27
+ $name = $this->getAttribute('name');
28
+
29
+ if ($this->getAttribute('is_defined_test')) {
30
+ if ($this->isSpecial()) {
31
+ $compiler->repr(true);
32
+ } else {
33
+ $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
34
+ }
35
+ } elseif ($this->isSpecial()) {
36
+ $compiler->raw($this->specialVars[$name]);
37
+ } elseif ($this->getAttribute('always_defined')) {
38
+ $compiler
39
+ ->raw('$context[')
40
+ ->string($name)
41
+ ->raw(']')
42
+ ;
43
+ } else {
44
+ // remove the non-PHP 5.4 version when PHP 5.3 support is dropped
45
+ // as the non-optimized version is just a workaround for slow ternary operator
46
+ // when the context has a lot of variables
47
+ if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
48
+ // PHP 5.4 ternary operator performance was optimized
49
+ $compiler
50
+ ->raw('(isset($context[')
51
+ ->string($name)
52
+ ->raw(']) ? $context[')
53
+ ->string($name)
54
+ ->raw('] : ')
55
+ ;
56
+
57
+ if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
58
+ $compiler->raw('null)');
59
+ } else {
60
+ $compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
61
+ }
62
+ } else {
63
+ $compiler
64
+ ->raw('$this->getContext($context, ')
65
+ ->string($name)
66
+ ;
67
+
68
+ if ($this->getAttribute('ignore_strict_check')) {
69
+ $compiler->raw(', true');
70
+ }
71
+
72
+ $compiler
73
+ ->raw(')')
74
+ ;
75
+ }
76
+ }
77
+ }
78
+
79
+ public function isSpecial()
80
+ {
81
+ return isset($this->specialVars[$this->getAttribute('name')]);
82
+ }
83
+
84
+ public function isSimple()
85
+ {
86
+ return !$this->isSpecial() && !$this->getAttribute('is_defined_test');
87
+ }
88
+ }
classes/Twig/Node/Expression/Parent.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a parent node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Expression_Parent extends Twig_Node_Expression
19
+ {
20
+ public function __construct($name, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ if ($this->getAttribute('output')) {
33
+ $compiler
34
+ ->addDebugInfo($this)
35
+ ->write("\$this->displayParentBlock(")
36
+ ->string($this->getAttribute('name'))
37
+ ->raw(", \$context, \$blocks);\n")
38
+ ;
39
+ } else {
40
+ $compiler
41
+ ->raw("\$this->renderParentBlock(")
42
+ ->string($this->getAttribute('name'))
43
+ ->raw(", \$context, \$blocks)")
44
+ ;
45
+ }
46
+ }
47
+ }
classes/Twig/Node/Expression/TempName.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_TempName extends Twig_Node_Expression
12
+ {
13
+ public function __construct($name, $lineno)
14
+ {
15
+ parent::__construct(array(), array('name' => $name), $lineno);
16
+ }
17
+
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $compiler
21
+ ->raw('$_')
22
+ ->raw($this->getAttribute('name'))
23
+ ->raw('_')
24
+ ;
25
+ }
26
+ }
classes/Twig/Node/Expression/Test.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
12
+ {
13
+ public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
14
+ {
15
+ parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno);
16
+ }
17
+
18
+ public function compile(Twig_Compiler $compiler)
19
+ {
20
+ $name = $this->getAttribute('name');
21
+ $test = $compiler->getEnvironment()->getTest($name);
22
+
23
+ $this->setAttribute('name', $name);
24
+ $this->setAttribute('type', 'test');
25
+ $this->setAttribute('thing', $test);
26
+ if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
27
+ $this->setAttribute('callable', $test->getCallable());
28
+ }
29
+
30
+ $this->compileCallable($compiler);
31
+ }
32
+ }
classes/Twig/Node/Expression/Test/Constant.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks if a variable is the exact same value as a constant.
14
+ *
15
+ * <pre>
16
+ * {% if post.status is constant('Post::PUBLISHED') %}
17
+ * the status attribute is exactly the same as Post::PUBLISHED
18
+ * {% endif %}
19
+ * </pre>
20
+ *
21
+ * @author Fabien Potencier <fabien@symfony.com>
22
+ */
23
+ class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
24
+ {
25
+ public function compile(Twig_Compiler $compiler)
26
+ {
27
+ $compiler
28
+ ->raw('(')
29
+ ->subcompile($this->getNode('node'))
30
+ ->raw(' === constant(')
31
+ ;
32
+
33
+ if ($this->getNode('arguments')->hasNode(1)) {
34
+ $compiler
35
+ ->raw('get_class(')
36
+ ->subcompile($this->getNode('arguments')->getNode(1))
37
+ ->raw(')."::".')
38
+ ;
39
+ }
40
+
41
+ $compiler
42
+ ->subcompile($this->getNode('arguments')->getNode(0))
43
+ ->raw('))')
44
+ ;
45
+ }
46
+ }
classes/Twig/Node/Expression/Test/Defined.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks if a variable is defined in the current context.
14
+ *
15
+ * <pre>
16
+ * {# defined works with variable names and variable attributes #}
17
+ * {% if foo is defined %}
18
+ * {# ... #}
19
+ * {% endif %}
20
+ * </pre>
21
+ *
22
+ * @author Fabien Potencier <fabien@symfony.com>
23
+ */
24
+ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
25
+ {
26
+ public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
27
+ {
28
+ parent::__construct($node, $name, $arguments, $lineno);
29
+
30
+ if ($node instanceof Twig_Node_Expression_Name) {
31
+ $node->setAttribute('is_defined_test', true);
32
+ } elseif ($node instanceof Twig_Node_Expression_GetAttr) {
33
+ $node->setAttribute('is_defined_test', true);
34
+
35
+ $this->changeIgnoreStrictCheck($node);
36
+ } else {
37
+ throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
38
+ }
39
+ }
40
+
41
+ protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
42
+ {
43
+ $node->setAttribute('ignore_strict_check', true);
44
+
45
+ if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) {
46
+ $this->changeIgnoreStrictCheck($node->getNode('node'));
47
+ }
48
+ }
49
+
50
+ public function compile(Twig_Compiler $compiler)
51
+ {
52
+ $compiler->subcompile($this->getNode('node'));
53
+ }
54
+ }
classes/Twig/Node/Expression/Test/Divisibleby.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks if a variable is divisible by a number.
14
+ *
15
+ * <pre>
16
+ * {% if loop.index is divisible by(3) %}
17
+ * </pre>
18
+ *
19
+ * @author Fabien Potencier <fabien@symfony.com>
20
+ */
21
+ class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
22
+ {
23
+ public function compile(Twig_Compiler $compiler)
24
+ {
25
+ $compiler
26
+ ->raw('(0 == ')
27
+ ->subcompile($this->getNode('node'))
28
+ ->raw(' % ')
29
+ ->subcompile($this->getNode('arguments')->getNode(0))
30
+ ->raw(')')
31
+ ;
32
+ }
33
+ }
classes/Twig/Node/Expression/Test/Even.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks if a number is even.
14
+ *
15
+ * <pre>
16
+ * {{ var is even }}
17
+ * </pre>
18
+ *
19
+ * @author Fabien Potencier <fabien@symfony.com>
20
+ */
21
+ class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
22
+ {
23
+ public function compile(Twig_Compiler $compiler)
24
+ {
25
+ $compiler
26
+ ->raw('(')
27
+ ->subcompile($this->getNode('node'))
28
+ ->raw(' % 2 == 0')
29
+ ->raw(')')
30
+ ;
31
+ }
32
+ }
classes/Twig/Node/Expression/Test/Null.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks that a variable is null.
14
+ *
15
+ * <pre>
16
+ * {{ var is none }}
17
+ * </pre>
18
+ *
19
+ * @author Fabien Potencier <fabien@symfony.com>
20
+ */
21
+ class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
22
+ {
23
+ public function compile(Twig_Compiler $compiler)
24
+ {
25
+ $compiler
26
+ ->raw('(null === ')
27
+ ->subcompile($this->getNode('node'))
28
+ ->raw(')')
29
+ ;
30
+ }
31
+ }
classes/Twig/Node/Expression/Test/Odd.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks if a number is odd.
14
+ *
15
+ * <pre>
16
+ * {{ var is odd }}
17
+ * </pre>
18
+ *
19
+ * @author Fabien Potencier <fabien@symfony.com>
20
+ */
21
+ class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
22
+ {
23
+ public function compile(Twig_Compiler $compiler)
24
+ {
25
+ $compiler
26
+ ->raw('(')
27
+ ->subcompile($this->getNode('node'))
28
+ ->raw(' % 2 == 1')
29
+ ->raw(')')
30
+ ;
31
+ }
32
+ }
classes/Twig/Node/Expression/Test/Sameas.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Checks if a variable is the same as another one (=== in PHP).
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
18
+ {
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ $compiler
22
+ ->raw('(')
23
+ ->subcompile($this->getNode('node'))
24
+ ->raw(' === ')
25
+ ->subcompile($this->getNode('arguments')->getNode(0))
26
+ ->raw(')')
27
+ ;
28
+ }
29
+ }
classes/Twig/Node/Expression/Unary.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
13
+ {
14
+ public function __construct(Twig_NodeInterface $node, $lineno)
15
+ {
16
+ parent::__construct(array('node' => $node), array(), $lineno);
17
+ }
18
+
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ $compiler->raw('(');
22
+ $this->operator($compiler);
23
+ $compiler
24
+ ->subcompile($this->getNode('node'))
25
+ ->raw(')')
26
+ ;
27
+ }
28
+
29
+ abstract public function operator(Twig_Compiler $compiler);
30
+ }
classes/Twig/Node/Expression/Unary/Neg.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ $compiler->raw('-');
17
+ }
18
+ }
classes/Twig/Node/Expression/Unary/Not.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ $compiler->raw('!');
17
+ }
18
+ }
classes/Twig/Node/Expression/Unary/Pos.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+ class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
13
+ {
14
+ public function operator(Twig_Compiler $compiler)
15
+ {
16
+ $compiler->raw('+');
17
+ }
18
+ }
classes/Twig/Node/Flush.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a flush node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Flush extends Twig_Node
18
+ {
19
+ public function __construct($lineno, $tag)
20
+ {
21
+ parent::__construct(array(), array(), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ $compiler
32
+ ->addDebugInfo($this)
33
+ ->write("flush();\n")
34
+ ;
35
+ }
36
+ }
classes/Twig/Node/For.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a for node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_For extends Twig_Node
19
+ {
20
+ protected $loop;
21
+
22
+ public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
23
+ {
24
+ $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag)));
25
+
26
+ if (null !== $ifexpr) {
27
+ $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag);
28
+ }
29
+
30
+ parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag);
31
+ }
32
+
33
+ /**
34
+ * Compiles the node to PHP.
35
+ *
36
+ * @param Twig_Compiler A Twig_Compiler instance
37
+ */
38
+ public function compile(Twig_Compiler $compiler)
39
+ {
40
+ $compiler
41
+ ->addDebugInfo($this)
42
+ // the (array) cast bypasses a PHP 5.2.6 bug
43
+ ->write("\$context['_parent'] = (array) \$context;\n")
44
+ ->write("\$context['_seq'] = twig_ensure_traversable(")
45
+ ->subcompile($this->getNode('seq'))
46
+ ->raw(");\n")
47
+ ;
48
+
49
+ if (null !== $this->getNode('else')) {
50
+ $compiler->write("\$context['_iterated'] = false;\n");
51
+ }
52
+
53
+ if ($this->getAttribute('with_loop')) {
54
+ $compiler
55
+ ->write("\$context['loop'] = array(\n")
56
+ ->write(" 'parent' => \$context['_parent'],\n")
57
+ ->write(" 'index0' => 0,\n")
58
+ ->write(" 'index' => 1,\n")
59
+ ->write(" 'first' => true,\n")
60
+ ->write(");\n")
61
+ ;
62
+
63
+ if (!$this->getAttribute('ifexpr')) {
64
+ $compiler
65
+ ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
66
+ ->indent()
67
+ ->write("\$length = count(\$context['_seq']);\n")
68
+ ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
69
+ ->write("\$context['loop']['revindex'] = \$length;\n")
70
+ ->write("\$context['loop']['length'] = \$length;\n")
71
+ ->write("\$context['loop']['last'] = 1 === \$length;\n")
72
+ ->outdent()
73
+ ->write("}\n")
74
+ ;
75
+ }
76
+ }
77
+
78
+ $this->loop->setAttribute('else', null !== $this->getNode('else'));
79
+ $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop'));
80
+ $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr'));
81
+
82
+ $compiler
83
+ ->write("foreach (\$context['_seq'] as ")
84
+ ->subcompile($this->getNode('key_target'))
85
+ ->raw(" => ")
86
+ ->subcompile($this->getNode('value_target'))
87
+ ->raw(") {\n")
88
+ ->indent()
89
+ ->subcompile($this->getNode('body'))
90
+ ->outdent()
91
+ ->write("}\n")
92
+ ;
93
+
94
+ if (null !== $this->getNode('else')) {
95
+ $compiler
96
+ ->write("if (!\$context['_iterated']) {\n")
97
+ ->indent()
98
+ ->subcompile($this->getNode('else'))
99
+ ->outdent()
100
+ ->write("}\n")
101
+ ;
102
+ }
103
+
104
+ $compiler->write("\$_parent = \$context['_parent'];\n");
105
+
106
+ // remove some "private" loop variables (needed for nested loops)
107
+ $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
108
+
109
+ // keep the values set in the inner context for variables defined in the outer context
110
+ $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
111
+ }
112
+ }
classes/Twig/Node/ForLoop.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Internal node used by the for node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_ForLoop extends Twig_Node
18
+ {
19
+ public function __construct($lineno, $tag = null)
20
+ {
21
+ parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ if ($this->getAttribute('else')) {
32
+ $compiler->write("\$context['_iterated'] = true;\n");
33
+ }
34
+
35
+ if ($this->getAttribute('with_loop')) {
36
+ $compiler
37
+ ->write("++\$context['loop']['index0'];\n")
38
+ ->write("++\$context['loop']['index'];\n")
39
+ ->write("\$context['loop']['first'] = false;\n")
40
+ ;
41
+
42
+ if (!$this->getAttribute('ifexpr')) {
43
+ $compiler
44
+ ->write("if (isset(\$context['loop']['length'])) {\n")
45
+ ->indent()
46
+ ->write("--\$context['loop']['revindex0'];\n")
47
+ ->write("--\$context['loop']['revindex'];\n")
48
+ ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
49
+ ->outdent()
50
+ ->write("}\n")
51
+ ;
52
+ }
53
+ }
54
+ }
55
+ }
classes/Twig/Node/If.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents an if node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_If extends Twig_Node
19
+ {
20
+ public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ $compiler->addDebugInfo($this);
33
+ for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) {
34
+ if ($i > 0) {
35
+ $compiler
36
+ ->outdent()
37
+ ->write("} elseif (")
38
+ ;
39
+ } else {
40
+ $compiler
41
+ ->write('if (')
42
+ ;
43
+ }
44
+
45
+ $compiler
46
+ ->subcompile($this->getNode('tests')->getNode($i))
47
+ ->raw(") {\n")
48
+ ->indent()
49
+ ->subcompile($this->getNode('tests')->getNode($i + 1))
50
+ ;
51
+ }
52
+
53
+ if ($this->hasNode('else') && null !== $this->getNode('else')) {
54
+ $compiler
55
+ ->outdent()
56
+ ->write("} else {\n")
57
+ ->indent()
58
+ ->subcompile($this->getNode('else'))
59
+ ;
60
+ }
61
+
62
+ $compiler
63
+ ->outdent()
64
+ ->write("}\n");
65
+ }
66
+ }
classes/Twig/Node/Import.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents an import node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Import extends Twig_Node
18
+ {
19
+ public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
20
+ {
21
+ parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ $compiler
32
+ ->addDebugInfo($this)
33
+ ->write('')
34
+ ->subcompile($this->getNode('var'))
35
+ ->raw(' = ')
36
+ ;
37
+
38
+ if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
39
+ $compiler->raw("\$this");
40
+ } else {
41
+ $compiler
42
+ ->raw('$this->env->loadTemplate(')
43
+ ->subcompile($this->getNode('expr'))
44
+ ->raw(")")
45
+ ;
46
+ }
47
+
48
+ $compiler->raw(";\n");
49
+ }
50
+ }
classes/Twig/Node/Include.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents an include node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
19
+ {
20
+ public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ $compiler->addDebugInfo($this);
33
+
34
+ if ($this->getAttribute('ignore_missing')) {
35
+ $compiler
36
+ ->write("try {\n")
37
+ ->indent()
38
+ ;
39
+ }
40
+
41
+ $this->addGetTemplate($compiler);
42
+
43
+ $compiler->raw('->display(');
44
+
45
+ $this->addTemplateArguments($compiler);
46
+
47
+ $compiler->raw(");\n");
48
+
49
+ if ($this->getAttribute('ignore_missing')) {
50
+ $compiler
51
+ ->outdent()
52
+ ->write("} catch (Twig_Error_Loader \$e) {\n")
53
+ ->indent()
54
+ ->write("// ignore missing template\n")
55
+ ->outdent()
56
+ ->write("}\n\n")
57
+ ;
58
+ }
59
+ }
60
+
61
+ protected function addGetTemplate(Twig_Compiler $compiler)
62
+ {
63
+ if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
64
+ $compiler
65
+ ->write("\$this->env->loadTemplate(")
66
+ ->subcompile($this->getNode('expr'))
67
+ ->raw(")")
68
+ ;
69
+ } else {
70
+ $compiler
71
+ ->write("\$template = \$this->env->resolveTemplate(")
72
+ ->subcompile($this->getNode('expr'))
73
+ ->raw(");\n")
74
+ ->write('$template')
75
+ ;
76
+ }
77
+ }
78
+
79
+ protected function addTemplateArguments(Twig_Compiler $compiler)
80
+ {
81
+ if (false === $this->getAttribute('only')) {
82
+ if (null === $this->getNode('variables')) {
83
+ $compiler->raw('$context');
84
+ } else {
85
+ $compiler
86
+ ->raw('array_merge($context, ')
87
+ ->subcompile($this->getNode('variables'))
88
+ ->raw(')')
89
+ ;
90
+ }
91
+ } else {
92
+ if (null === $this->getNode('variables')) {
93
+ $compiler->raw('array()');
94
+ } else {
95
+ $compiler->subcompile($this->getNode('variables'));
96
+ }
97
+ }
98
+ }
99
+ }
classes/Twig/Node/Macro.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a macro node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Macro extends Twig_Node
18
+ {
19
+ public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
20
+ {
21
+ parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ $compiler
32
+ ->addDebugInfo($this)
33
+ ->write(sprintf("public function get%s(", $this->getAttribute('name')))
34
+ ;
35
+
36
+ $count = count($this->getNode('arguments'));
37
+ $pos = 0;
38
+ foreach ($this->getNode('arguments') as $name => $default) {
39
+ $compiler
40
+ ->raw('$_'.$name.' = ')
41
+ ->subcompile($default)
42
+ ;
43
+
44
+ if (++$pos < $count) {
45
+ $compiler->raw(', ');
46
+ }
47
+ }
48
+
49
+ $compiler
50
+ ->raw(")\n")
51
+ ->write("{\n")
52
+ ->indent()
53
+ ;
54
+
55
+ if (!count($this->getNode('arguments'))) {
56
+ $compiler->write("\$context = \$this->env->getGlobals();\n\n");
57
+ } else {
58
+ $compiler
59
+ ->write("\$context = \$this->env->mergeGlobals(array(\n")
60
+ ->indent()
61
+ ;
62
+
63
+ foreach ($this->getNode('arguments') as $name => $default) {
64
+ $compiler
65
+ ->write('')
66
+ ->string($name)
67
+ ->raw(' => $_'.$name)
68
+ ->raw(",\n")
69
+ ;
70
+ }
71
+
72
+ $compiler
73
+ ->outdent()
74
+ ->write("));\n\n")
75
+ ;
76
+ }
77
+
78
+ $compiler
79
+ ->write("\$blocks = array();\n\n")
80
+ ->write("ob_start();\n")
81
+ ->write("try {\n")
82
+ ->indent()
83
+ ->subcompile($this->getNode('body'))
84
+ ->outdent()
85
+ ->write("} catch (Exception \$e) {\n")
86
+ ->indent()
87
+ ->write("ob_end_clean();\n\n")
88
+ ->write("throw \$e;\n")
89
+ ->outdent()
90
+ ->write("}\n\n")
91
+ ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
92
+ ->outdent()
93
+ ->write("}\n\n")
94
+ ;
95
+ }
96
+ }
classes/Twig/Node/Module.php ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a module node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Module extends Twig_Node
19
+ {
20
+ public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
21
+ {
22
+ // embedded templates are set as attributes so that they are only visited once by the visitors
23
+ parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1);
24
+ }
25
+
26
+ public function setIndex($index)
27
+ {
28
+ $this->setAttribute('index', $index);
29
+ }
30
+
31
+ /**
32
+ * Compiles the node to PHP.
33
+ *
34
+ * @param Twig_Compiler A Twig_Compiler instance
35
+ */
36
+ public function compile(Twig_Compiler $compiler)
37
+ {
38
+ $this->compileTemplate($compiler);
39
+
40
+ foreach ($this->getAttribute('embedded_templates') as $template) {
41
+ $compiler->subcompile($template);
42
+ }
43
+ }
44
+
45
+ protected function compileTemplate(Twig_Compiler $compiler)
46
+ {
47
+ if (!$this->getAttribute('index')) {
48
+ $compiler->write('<?php');
49
+ }
50
+
51
+ $this->compileClassHeader($compiler);
52
+
53
+ if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
54
+ $this->compileConstructor($compiler);
55
+ }
56
+
57
+ $this->compileGetParent($compiler);
58
+
59
+ $this->compileDisplayHeader($compiler);
60
+
61
+ $this->compileDisplayBody($compiler);
62
+
63
+ $this->compileDisplayFooter($compiler);
64
+
65
+ $compiler->subcompile($this->getNode('blocks'));
66
+
67
+ $this->compileMacros($compiler);
68
+
69
+ $this->compileGetTemplateName($compiler);
70
+
71
+ $this->compileIsTraitable($compiler);
72
+
73
+ $this->compileDebugInfo($compiler);
74
+
75
+ $this->compileClassFooter($compiler);
76
+ }
77
+
78
+ protected function compileGetParent(Twig_Compiler $compiler)
79
+ {
80
+ if (null === $this->getNode('parent')) {
81
+ return;
82
+ }
83
+
84
+ $compiler
85
+ ->write("protected function doGetParent(array \$context)\n", "{\n")
86
+ ->indent()
87
+ ->write("return ")
88
+ ;
89
+
90
+ if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
91
+ $compiler->subcompile($this->getNode('parent'));
92
+ } else {
93
+ $compiler
94
+ ->raw("\$this->env->resolveTemplate(")
95
+ ->subcompile($this->getNode('parent'))
96
+ ->raw(")")
97
+ ;
98
+ }
99
+
100
+ $compiler
101
+ ->raw(";\n")
102
+ ->outdent()
103
+ ->write("}\n\n")
104
+ ;
105
+ }
106
+
107
+ protected function compileDisplayBody(Twig_Compiler $compiler)
108
+ {
109
+ $compiler->subcompile($this->getNode('body'));
110
+
111
+ if (null !== $this->getNode('parent')) {
112
+ if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
113
+ $compiler->write("\$this->parent");
114
+ } else {
115
+ $compiler->write("\$this->getParent(\$context)");
116
+ }
117
+ $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
118
+ }
119
+ }
120
+
121
+ protected function compileClassHeader(Twig_Compiler $compiler)
122
+ {
123
+ $compiler
124
+ ->write("\n\n")
125
+ // if the filename contains */, add a blank to avoid a PHP parse error
126
+ ->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
127
+ ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
128
+ ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
129
+ ->write("{\n")
130
+ ->indent()
131
+ ;
132
+ }
133
+
134
+ protected function compileConstructor(Twig_Compiler $compiler)
135
+ {
136
+ $compiler
137
+ ->write("public function __construct(Twig_Environment \$env)\n", "{\n")
138
+ ->indent()
139
+ ->write("parent::__construct(\$env);\n\n")
140
+ ;
141
+
142
+ // parent
143
+ if (null === $this->getNode('parent')) {
144
+ $compiler->write("\$this->parent = false;\n\n");
145
+ } elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
146
+ $compiler
147
+ ->write("\$this->parent = \$this->env->loadTemplate(")
148
+ ->subcompile($this->getNode('parent'))
149
+ ->raw(");\n\n")
150
+ ;
151
+ }
152
+
153
+ $countTraits = count($this->getNode('traits'));
154
+ if ($countTraits) {
155
+ // traits
156
+ foreach ($this->getNode('traits') as $i => $trait) {
157
+ $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
158
+
159
+ $compiler
160
+ ->addDebugInfo($trait->getNode('template'))
161
+ ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
162
+ ->indent()
163
+ ->write("throw new Twig_Error_Runtime('Template \"'.")
164
+ ->subcompile($trait->getNode('template'))
165
+ ->raw(".'\" cannot be used as a trait.');\n")
166
+ ->outdent()
167
+ ->write("}\n")
168
+ ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
169
+ ;
170
+
171
+ foreach ($trait->getNode('targets') as $key => $value) {
172
+ $compiler
173
+ ->write(sprintf("if (!isset(\$_trait_%s_blocks[", $i))
174
+ ->string($key)
175
+ ->raw("])) {\n")
176
+ ->indent()
177
+ ->write("throw new Twig_Error_Runtime(sprintf('Block ")
178
+ ->string($key)
179
+ ->raw(" is not defined in trait ")
180
+ ->subcompile($trait->getNode('template'))
181
+ ->raw(".'));\n")
182
+ ->outdent()
183
+ ->write("}\n\n")
184
+
185
+ ->write(sprintf("\$_trait_%s_blocks[", $i))
186
+ ->subcompile($value)
187
+ ->raw(sprintf("] = \$_trait_%s_blocks[", $i))
188
+ ->string($key)
189
+ ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
190
+ ->string($key)
191
+ ->raw("]);\n\n")
192
+ ;
193
+ }
194
+ }
195
+
196
+ if ($countTraits > 1) {
197
+ $compiler
198
+ ->write("\$this->traits = array_merge(\n")
199
+ ->indent()
200
+ ;
201
+
202
+ for ($i = 0; $i < $countTraits; $i++) {
203
+ $compiler
204
+ ->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i))
205
+ ;
206
+ }
207
+
208
+ $compiler
209
+ ->outdent()
210
+ ->write(");\n\n")
211
+ ;
212
+ } else {
213
+ $compiler
214
+ ->write("\$this->traits = \$_trait_0_blocks;\n\n")
215
+ ;
216
+ }
217
+
218
+ $compiler
219
+ ->write("\$this->blocks = array_merge(\n")
220
+ ->indent()
221
+ ->write("\$this->traits,\n")
222
+ ->write("array(\n")
223
+ ;
224
+ } else {
225
+ $compiler
226
+ ->write("\$this->blocks = array(\n")
227
+ ;
228
+ }
229
+
230
+ // blocks
231
+ $compiler
232
+ ->indent()
233
+ ;
234
+
235
+ foreach ($this->getNode('blocks') as $name => $node) {
236
+ $compiler
237
+ ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
238
+ ;
239
+ }
240
+
241
+ if ($countTraits) {
242
+ $compiler
243
+ ->outdent()
244
+ ->write(")\n")
245
+ ;
246
+ }
247
+
248
+ $compiler
249
+ ->outdent()
250
+ ->write(");\n")
251
+ ->outdent()
252
+ ->write("}\n\n");
253
+ ;
254
+ }
255
+
256
+ protected function compileDisplayHeader(Twig_Compiler $compiler)
257
+ {
258
+ $compiler
259
+ ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
260
+ ->indent()
261
+ ;
262
+ }
263
+
264
+ protected function compileDisplayFooter(Twig_Compiler $compiler)
265
+ {
266
+ $compiler
267
+ ->outdent()
268
+ ->write("}\n\n")
269
+ ;
270
+ }
271
+
272
+ protected function compileClassFooter(Twig_Compiler $compiler)
273
+ {
274
+ $compiler
275
+ ->outdent()
276
+ ->write("}\n")
277
+ ;
278
+ }
279
+
280
+ protected function compileMacros(Twig_Compiler $compiler)
281
+ {
282
+ $compiler->subcompile($this->getNode('macros'));
283
+ }
284
+
285
+ protected function compileGetTemplateName(Twig_Compiler $compiler)
286
+ {
287
+ $compiler
288
+ ->write("public function getTemplateName()\n", "{\n")
289
+ ->indent()
290
+ ->write('return ')
291
+ ->repr($this->getAttribute('filename'))
292
+ ->raw(";\n")
293
+ ->outdent()
294
+ ->write("}\n\n")
295
+ ;
296
+ }
297
+
298
+ protected function compileIsTraitable(Twig_Compiler $compiler)
299
+ {
300
+ // A template can be used as a trait if:
301
+ // * it has no parent
302
+ // * it has no macros
303
+ // * it has no body
304
+ //
305
+ // Put another way, a template can be used as a trait if it
306
+ // only contains blocks and use statements.
307
+ $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros'));
308
+ if ($traitable) {
309
+ if ($this->getNode('body') instanceof Twig_Node_Body) {
310
+ $nodes = $this->getNode('body')->getNode(0);
311
+ } else {
312
+ $nodes = $this->getNode('body');
313
+ }
314
+
315
+ if (!count($nodes)) {
316
+ $nodes = new Twig_Node(array($nodes));
317
+ }
318
+
319
+ foreach ($nodes as $node) {
320
+ if (!count($node)) {
321
+ continue;
322
+ }
323
+
324
+ if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
325
+ continue;
326
+ }
327
+
328
+ if ($node instanceof Twig_Node_BlockReference) {
329
+ continue;
330
+ }
331
+
332
+ $traitable = false;
333
+ break;
334
+ }
335
+ }
336
+
337
+ if ($traitable) {
338
+ return;
339
+ }
340
+
341
+ $compiler
342
+ ->write("public function isTraitable()\n", "{\n")
343
+ ->indent()
344
+ ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
345
+ ->outdent()
346
+ ->write("}\n\n")
347
+ ;
348
+ }
349
+
350
+ protected function compileDebugInfo(Twig_Compiler $compiler)
351
+ {
352
+ $compiler
353
+ ->write("public function getDebugInfo()\n", "{\n")
354
+ ->indent()
355
+ ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
356
+ ->outdent()
357
+ ->write("}\n")
358
+ ;
359
+ }
360
+
361
+ protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
362
+ {
363
+ if ($node instanceof Twig_Node_Expression_Constant) {
364
+ $compiler
365
+ ->write(sprintf("%s = \$this->env->loadTemplate(", $var))
366
+ ->subcompile($node)
367
+ ->raw(");\n")
368
+ ;
369
+ } else {
370
+ $compiler
371
+ ->write(sprintf("%s = ", $var))
372
+ ->subcompile($node)
373
+ ->raw(";\n")
374
+ ->write(sprintf("if (!%s", $var))
375
+ ->raw(" instanceof Twig_Template) {\n")
376
+ ->indent()
377
+ ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
378
+ ->outdent()
379
+ ->write("}\n")
380
+ ;
381
+ }
382
+ }
383
+ }
classes/Twig/Node/Print.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a node that outputs an expression.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
19
+ {
20
+ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
21
+ {
22
+ parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ $compiler
33
+ ->addDebugInfo($this)
34
+ ->write('echo ')
35
+ ->subcompile($this->getNode('expr'))
36
+ ->raw(";\n")
37
+ ;
38
+ }
39
+ }
classes/Twig/Node/Sandbox.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a sandbox node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Sandbox extends Twig_Node
18
+ {
19
+ public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
20
+ {
21
+ parent::__construct(array('body' => $body), array(), $lineno, $tag);
22
+ }
23
+
24
+ /**
25
+ * Compiles the node to PHP.
26
+ *
27
+ * @param Twig_Compiler A Twig_Compiler instance
28
+ */
29
+ public function compile(Twig_Compiler $compiler)
30
+ {
31
+ $compiler
32
+ ->addDebugInfo($this)
33
+ ->write("\$sandbox = \$this->env->getExtension('sandbox');\n")
34
+ ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
35
+ ->indent()
36
+ ->write("\$sandbox->enableSandbox();\n")
37
+ ->outdent()
38
+ ->write("}\n")
39
+ ->subcompile($this->getNode('body'))
40
+ ->write("if (!\$alreadySandboxed) {\n")
41
+ ->indent()
42
+ ->write("\$sandbox->disableSandbox();\n")
43
+ ->outdent()
44
+ ->write("}\n")
45
+ ;
46
+ }
47
+ }
classes/Twig/Node/SandboxedModule.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a module node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_SandboxedModule extends Twig_Node_Module
19
+ {
20
+ protected $usedFilters;
21
+ protected $usedTags;
22
+ protected $usedFunctions;
23
+
24
+ public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags, array $usedFunctions)
25
+ {
26
+ parent::__construct($node->getNode('body'), $node->getNode('parent'), $node->getNode('blocks'), $node->getNode('macros'), $node->getNode('traits'), $node->getAttribute('embedded_templates'), $node->getAttribute('filename'));
27
+
28
+ $this->setAttribute('index', $node->getAttribute('index'));
29
+
30
+ $this->usedFilters = $usedFilters;
31
+ $this->usedTags = $usedTags;
32
+ $this->usedFunctions = $usedFunctions;
33
+ }
34
+
35
+ protected function compileDisplayBody(Twig_Compiler $compiler)
36
+ {
37
+ $compiler->write("\$this->checkSecurity();\n");
38
+
39
+ parent::compileDisplayBody($compiler);
40
+ }
41
+
42
+ protected function compileDisplayFooter(Twig_Compiler $compiler)
43
+ {
44
+ parent::compileDisplayFooter($compiler);
45
+
46
+ $compiler
47
+ ->write("protected function checkSecurity()\n", "{\n")
48
+ ->indent()
49
+ ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
50
+ ->indent()
51
+ ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n")
52
+ ->write(!$this->usedFilters ? "array(),\n" : "array('".implode('\', \'', $this->usedFilters)."'),\n")
53
+ ->write(!$this->usedFunctions ? "array()\n" : "array('".implode('\', \'', $this->usedFunctions)."')\n")
54
+ ->outdent()
55
+ ->write(");\n")
56
+ ->outdent()
57
+ ->write("}\n\n")
58
+ ;
59
+ }
60
+ }
classes/Twig/Node/SandboxedPrint.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig_Node_SandboxedPrint adds a check for the __toString() method
14
+ * when the variable is an object and the sandbox is activated.
15
+ *
16
+ * When there is a simple Print statement, like {{ article }},
17
+ * and if the sandbox is enabled, we need to check that the __toString()
18
+ * method is allowed if 'article' is an object.
19
+ *
20
+ * @author Fabien Potencier <fabien@symfony.com>
21
+ */
22
+ class Twig_Node_SandboxedPrint extends Twig_Node_Print
23
+ {
24
+ public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
25
+ {
26
+ parent::__construct($expr, $lineno, $tag);
27
+ }
28
+
29
+ /**
30
+ * Compiles the node to PHP.
31
+ *
32
+ * @param Twig_Compiler A Twig_Compiler instance
33
+ */
34
+ public function compile(Twig_Compiler $compiler)
35
+ {
36
+ $compiler
37
+ ->addDebugInfo($this)
38
+ ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(')
39
+ ->subcompile($this->getNode('expr'))
40
+ ->raw(");\n")
41
+ ;
42
+ }
43
+
44
+ /**
45
+ * Removes node filters.
46
+ *
47
+ * This is mostly needed when another visitor adds filters (like the escaper one).
48
+ *
49
+ * @param Twig_Node $node A Node
50
+ */
51
+ protected function removeNodeFilter($node)
52
+ {
53
+ if ($node instanceof Twig_Node_Expression_Filter) {
54
+ return $this->removeNodeFilter($node->getNode('node'));
55
+ }
56
+
57
+ return $node;
58
+ }
59
+ }
classes/Twig/Node/Set.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a set node.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Node_Set extends Twig_Node
18
+ {
19
+ public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
20
+ {
21
+ parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag);
22
+
23
+ /*
24
+ * Optimizes the node when capture is used for a large block of text.
25
+ *
26
+ * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo");
27
+ */
28
+ if ($this->getAttribute('capture')) {
29
+ $this->setAttribute('safe', true);
30
+
31
+ $values = $this->getNode('values');
32
+ if ($values instanceof Twig_Node_Text) {
33
+ $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getLine()));
34
+ $this->setAttribute('capture', false);
35
+ }
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Compiles the node to PHP.
41
+ *
42
+ * @param Twig_Compiler A Twig_Compiler instance
43
+ */
44
+ public function compile(Twig_Compiler $compiler)
45
+ {
46
+ $compiler->addDebugInfo($this);
47
+
48
+ if (count($this->getNode('names')) > 1) {
49
+ $compiler->write('list(');
50
+ foreach ($this->getNode('names') as $idx => $node) {
51
+ if ($idx) {
52
+ $compiler->raw(', ');
53
+ }
54
+
55
+ $compiler->subcompile($node);
56
+ }
57
+ $compiler->raw(')');
58
+ } else {
59
+ if ($this->getAttribute('capture')) {
60
+ $compiler
61
+ ->write("ob_start();\n")
62
+ ->subcompile($this->getNode('values'))
63
+ ;
64
+ }
65
+
66
+ $compiler->subcompile($this->getNode('names'), false);
67
+
68
+ if ($this->getAttribute('capture')) {
69
+ $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())");
70
+ }
71
+ }
72
+
73
+ if (!$this->getAttribute('capture')) {
74
+ $compiler->raw(' = ');
75
+
76
+ if (count($this->getNode('names')) > 1) {
77
+ $compiler->write('array(');
78
+ foreach ($this->getNode('values') as $idx => $value) {
79
+ if ($idx) {
80
+ $compiler->raw(', ');
81
+ }
82
+
83
+ $compiler->subcompile($value);
84
+ }
85
+ $compiler->raw(')');
86
+ } else {
87
+ if ($this->getAttribute('safe')) {
88
+ $compiler
89
+ ->raw("('' === \$tmp = ")
90
+ ->subcompile($this->getNode('values'))
91
+ ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())")
92
+ ;
93
+ } else {
94
+ $compiler->subcompile($this->getNode('values'));
95
+ }
96
+ }
97
+ }
98
+
99
+ $compiler->raw(";\n");
100
+ }
101
+ }
classes/Twig/Node/SetTemp.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ class Twig_Node_SetTemp extends Twig_Node
13
+ {
14
+ public function __construct($name, $lineno)
15
+ {
16
+ parent::__construct(array(), array('name' => $name), $lineno);
17
+ }
18
+
19
+ public function compile(Twig_Compiler $compiler)
20
+ {
21
+ $name = $this->getAttribute('name');
22
+ $compiler
23
+ ->addDebugInfo($this)
24
+ ->write('if (isset($context[')
25
+ ->string($name)
26
+ ->raw('])) { $_')
27
+ ->raw($name)
28
+ ->raw('_ = $context[')
29
+ ->repr($name)
30
+ ->raw(']; } else { $_')
31
+ ->raw($name)
32
+ ->raw("_ = null; }\n")
33
+ ;
34
+ }
35
+ }
classes/Twig/Node/Spaceless.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a spaceless node.
14
+ *
15
+ * It removes spaces between HTML tags.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ */
19
+ class Twig_Node_Spaceless extends Twig_Node
20
+ {
21
+ public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
22
+ {
23
+ parent::__construct(array('body' => $body), array(), $lineno, $tag);
24
+ }
25
+
26
+ /**
27
+ * Compiles the node to PHP.
28
+ *
29
+ * @param Twig_Compiler A Twig_Compiler instance
30
+ */
31
+ public function compile(Twig_Compiler $compiler)
32
+ {
33
+ $compiler
34
+ ->addDebugInfo($this)
35
+ ->write("ob_start();\n")
36
+ ->subcompile($this->getNode('body'))
37
+ ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
38
+ ;
39
+ }
40
+ }
classes/Twig/Node/Text.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a text node.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
19
+ {
20
+ public function __construct($data, $lineno)
21
+ {
22
+ parent::__construct(array(), array('data' => $data), $lineno);
23
+ }
24
+
25
+ /**
26
+ * Compiles the node to PHP.
27
+ *
28
+ * @param Twig_Compiler A Twig_Compiler instance
29
+ */
30
+ public function compile(Twig_Compiler $compiler)
31
+ {
32
+ $compiler
33
+ ->addDebugInfo($this)
34
+ ->write('echo ')
35
+ ->string($this->getAttribute('data'))
36
+ ->raw(";\n")
37
+ ;
38
+ }
39
+ }
classes/Twig/NodeInterface.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a node in the AST.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ *
17
+ * @deprecated since 1.12 (to be removed in 3.0)
18
+ */
19
+ interface Twig_NodeInterface extends Countable, IteratorAggregate
20
+ {
21
+ /**
22
+ * Compiles the node to PHP.
23
+ *
24
+ * @param Twig_Compiler A Twig_Compiler instance
25
+ */
26
+ public function compile(Twig_Compiler $compiler);
27
+
28
+ public function getLine();
29
+
30
+ public function getNodeTag();
31
+ }
classes/Twig/NodeOutputInterface.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a displayable node in the AST.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ interface Twig_NodeOutputInterface
18
+ {
19
+ }
classes/Twig/NodeTraverser.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig_NodeTraverser is a node traverser.
14
+ *
15
+ * It visits all nodes and their children and calls the given visitor for each.
16
+ *
17
+ * @author Fabien Potencier <fabien@symfony.com>
18
+ */
19
+ class Twig_NodeTraverser
20
+ {
21
+ protected $env;
22
+ protected $visitors;
23
+
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @param Twig_Environment $env A Twig_Environment instance
28
+ * @param Twig_NodeVisitorInterface[] $visitors An array of Twig_NodeVisitorInterface instances
29
+ */
30
+ public function __construct(Twig_Environment $env, array $visitors = array())
31
+ {
32
+ $this->env = $env;
33
+ $this->visitors = array();
34
+ foreach ($visitors as $visitor) {
35
+ $this->addVisitor($visitor);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Adds a visitor.
41
+ *
42
+ * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
43
+ */
44
+ public function addVisitor(Twig_NodeVisitorInterface $visitor)
45
+ {
46
+ if (!isset($this->visitors[$visitor->getPriority()])) {
47
+ $this->visitors[$visitor->getPriority()] = array();
48
+ }
49
+
50
+ $this->visitors[$visitor->getPriority()][] = $visitor;
51
+ }
52
+
53
+ /**
54
+ * Traverses a node and calls the registered visitors.
55
+ *
56
+ * @param Twig_NodeInterface $node A Twig_NodeInterface instance
57
+ */
58
+ public function traverse(Twig_NodeInterface $node)
59
+ {
60
+ ksort($this->visitors);
61
+ foreach ($this->visitors as $visitors) {
62
+ foreach ($visitors as $visitor) {
63
+ $node = $this->traverseForVisitor($visitor, $node);
64
+ }
65
+ }
66
+
67
+ return $node;
68
+ }
69
+
70
+ protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null)
71
+ {
72
+ if (null === $node) {
73
+ return;
74
+ }
75
+
76
+ $node = $visitor->enterNode($node, $this->env);
77
+
78
+ foreach ($node as $k => $n) {
79
+ if (false !== $n = $this->traverseForVisitor($visitor, $n)) {
80
+ $node->setNode($k, $n);
81
+ } else {
82
+ $node->removeNode($k);
83
+ }
84
+ }
85
+
86
+ return $visitor->leaveNode($node, $this->env);
87
+ }
88
+ }
classes/Twig/NodeVisitor/Escaper.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig_NodeVisitor_Escaper implements output escaping.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
18
+ {
19
+ protected $statusStack = array();
20
+ protected $blocks = array();
21
+ protected $safeAnalysis;
22
+ protected $traverser;
23
+ protected $defaultStrategy = false;
24
+ protected $safeVars = array();
25
+
26
+ public function __construct()
27
+ {
28
+ $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
29
+ }
30
+
31
+ /**
32
+ * Called before child nodes are visited.
33
+ *
34
+ * @param Twig_NodeInterface $node The node to visit
35
+ * @param Twig_Environment $env The Twig environment instance
36
+ *
37
+ * @return Twig_NodeInterface The modified node
38
+ */
39
+ public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
40
+ {
41
+ if ($node instanceof Twig_Node_Module) {
42
+ if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
43
+ $this->defaultStrategy = $defaultStrategy;
44
+ }
45
+ $this->safeVars = array();
46
+ } elseif ($node instanceof Twig_Node_AutoEscape) {
47
+ $this->statusStack[] = $node->getAttribute('value');
48
+ } elseif ($node instanceof Twig_Node_Block) {
49
+ $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
50
+ } elseif ($node instanceof Twig_Node_Import) {
51
+ $this->safeVars[] = $node->getNode('var')->getAttribute('name');
52
+ }
53
+
54
+ return $node;
55
+ }
56
+
57
+ /**
58
+ * Called after child nodes are visited.
59
+ *
60
+ * @param Twig_NodeInterface $node The node to visit
61
+ * @param Twig_Environment $env The Twig environment instance
62
+ *
63
+ * @return Twig_NodeInterface The modified node
64
+ */
65
+ public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
66
+ {
67
+ if ($node instanceof Twig_Node_Module) {
68
+ $this->defaultStrategy = false;
69
+ $this->safeVars = array();
70
+ } elseif ($node instanceof Twig_Node_Expression_Filter) {
71
+ return $this->preEscapeFilterNode($node, $env);
72
+ } elseif ($node instanceof Twig_Node_Print) {
73
+ return $this->escapePrintNode($node, $env, $this->needEscaping($env));
74
+ }
75
+
76
+ if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) {
77
+ array_pop($this->statusStack);
78
+ } elseif ($node instanceof Twig_Node_BlockReference) {
79
+ $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
80
+ }
81
+
82
+ return $node;
83
+ }
84
+
85
+ protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type)
86
+ {
87
+ if (false === $type) {
88
+ return $node;
89
+ }
90
+
91
+ $expression = $node->getNode('expr');
92
+
93
+ if ($this->isSafeFor($type, $expression, $env)) {
94
+ return $node;
95
+ }
96
+
97
+ $class = get_class($node);
98
+
99
+ return new $class(
100
+ $this->getEscaperFilter($type, $expression),
101
+ $node->getLine()
102
+ );
103
+ }
104
+
105
+ protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env)
106
+ {
107
+ $name = $filter->getNode('filter')->getAttribute('value');
108
+
109
+ $type = $env->getFilter($name)->getPreEscape();
110
+ if (null === $type) {
111
+ return $filter;
112
+ }
113
+
114
+ $node = $filter->getNode('node');
115
+ if ($this->isSafeFor($type, $node, $env)) {
116
+ return $filter;
117
+ }
118
+
119
+ $filter->setNode('node', $this->getEscaperFilter($type, $node));
120
+
121
+ return $filter;
122
+ }
123
+
124
+ protected function isSafeFor($type, Twig_NodeInterface $expression, $env)
125
+ {
126
+ $safe = $this->safeAnalysis->getSafe($expression);
127
+
128
+ if (null === $safe) {
129
+ if (null === $this->traverser) {
130
+ $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
131
+ }
132
+
133
+ $this->safeAnalysis->setSafeVars($this->safeVars);
134
+
135
+ $this->traverser->traverse($expression);
136
+ $safe = $this->safeAnalysis->getSafe($expression);
137
+ }
138
+
139
+ return in_array($type, $safe) || in_array('all', $safe);
140
+ }
141
+
142
+ protected function needEscaping(Twig_Environment $env)
143
+ {
144
+ if (count($this->statusStack)) {
145
+ return $this->statusStack[count($this->statusStack) - 1];
146
+ }
147
+
148
+ return $this->defaultStrategy ? $this->defaultStrategy : false;
149
+ }
150
+
151
+ protected function getEscaperFilter($type, Twig_NodeInterface $node)
152
+ {
153
+ $line = $node->getLine();
154
+ $name = new Twig_Node_Expression_Constant('escape', $line);
155
+ $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line)));
156
+
157
+ return new Twig_Node_Expression_Filter($node, $name, $args, $line);
158
+ }
159
+
160
+ /**
161
+ * {@inheritdoc}
162
+ */
163
+ public function getPriority()
164
+ {
165
+ return 0;
166
+ }
167
+ }
classes/Twig/NodeVisitor/Optimizer.php ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig_NodeVisitor_Optimizer tries to optimizes the AST.
14
+ *
15
+ * This visitor is always the last registered one.
16
+ *
17
+ * You can configure which optimizations you want to activate via the
18
+ * optimizer mode.
19
+ *
20
+ * @author Fabien Potencier <fabien@symfony.com>
21
+ */
22
+ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
23
+ {
24
+ const OPTIMIZE_ALL = -1;
25
+ const OPTIMIZE_NONE = 0;
26
+ const OPTIMIZE_FOR = 2;
27
+ const OPTIMIZE_RAW_FILTER = 4;
28
+ const OPTIMIZE_VAR_ACCESS = 8;
29
+
30
+ protected $loops = array();
31
+ protected $optimizers;
32
+ protected $prependedNodes = array();
33
+ protected $inABody = false;
34
+
35
+ /**
36
+ * Constructor.
37
+ *
38
+ * @param int $optimizers The optimizer mode
39
+ */
40
+ public function __construct($optimizers = -1)
41
+ {
42
+ if (!is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) {
43
+ throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
44
+ }
45
+
46
+ $this->optimizers = $optimizers;
47
+ }
48
+
49
+ /**
50
+ * {@inheritdoc}
51
+ */
52
+ public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
53
+ {
54
+ if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
55
+ $this->enterOptimizeFor($node, $env);
56
+ }
57
+
58
+ if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
59
+ if ($this->inABody) {
60
+ if (!$node instanceof Twig_Node_Expression) {
61
+ if (get_class($node) !== 'Twig_Node') {
62
+ array_unshift($this->prependedNodes, array());
63
+ }
64
+ } else {
65
+ $node = $this->optimizeVariables($node, $env);
66
+ }
67
+ } elseif ($node instanceof Twig_Node_Body) {
68
+ $this->inABody = true;
69
+ }
70
+ }
71
+
72
+ return $node;
73
+ }
74
+
75
+ /**
76
+ * {@inheritdoc}
77
+ */
78
+ public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
79
+ {
80
+ $expression = $node instanceof Twig_Node_Expression;
81
+
82
+ if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
83
+ $this->leaveOptimizeFor($node, $env);
84
+ }
85
+
86
+ if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) {
87
+ $node = $this->optimizeRawFilter($node, $env);
88
+ }
89
+
90
+ $node = $this->optimizePrintNode($node, $env);
91
+
92
+ if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
93
+ if ($node instanceof Twig_Node_Body) {
94
+ $this->inABody = false;
95
+ } elseif ($this->inABody) {
96
+ if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
97
+ $nodes = array();
98
+ foreach (array_unique($prependedNodes) as $name) {
99
+ $nodes[] = new Twig_Node_SetTemp($name, $node->getLine());
100
+ }
101
+
102
+ $nodes[] = $node;
103
+ $node = new Twig_Node($nodes);
104
+ }
105
+ }
106
+ }
107
+
108
+ return $node;
109
+ }
110
+
111
+ protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env)
112
+ {
113
+ if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
114
+ $this->prependedNodes[0][] = $node->getAttribute('name');
115
+
116
+ return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getLine());
117
+ }
118
+
119
+ return $node;
120
+ }
121
+
122
+ /**
123
+ * Optimizes print nodes.
124
+ *
125
+ * It replaces:
126
+ *
127
+ * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
128
+ *
129
+ * @param Twig_NodeInterface $node A Node
130
+ * @param Twig_Environment $env The current Twig environment
131
+ */
132
+ protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
133
+ {
134
+ if (!$node instanceof Twig_Node_Print) {
135
+ return $node;
136
+ }
137
+
138
+ if (
139
+ $node->getNode('expr') instanceof Twig_Node_Expression_BlockReference ||
140
+ $node->getNode('expr') instanceof Twig_Node_Expression_Parent
141
+ ) {
142
+ $node->getNode('expr')->setAttribute('output', true);
143
+
144
+ return $node->getNode('expr');
145
+ }
146
+
147
+ return $node;
148
+ }
149
+
150
+ /**
151
+ * Removes "raw" filters.
152
+ *
153
+ * @param Twig_NodeInterface $node A Node
154
+ * @param Twig_Environment $env The current Twig environment
155
+ */
156
+ protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
157
+ {
158
+ if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
159
+ return $node->getNode('node');
160
+ }
161
+
162
+ return $node;
163
+ }
164
+
165
+ /**
166
+ * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
167
+ *
168
+ * @param Twig_NodeInterface $node A Node
169
+ * @param Twig_Environment $env The current Twig environment
170
+ */
171
+ protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
172
+ {
173
+ if ($node instanceof Twig_Node_For) {
174
+ // disable the loop variable by default
175
+ $node->setAttribute('with_loop', false);
176
+ array_unshift($this->loops, $node);
177
+ } elseif (!$this->loops) {
178
+ // we are outside a loop
179
+ return;
180
+ }
181
+
182
+ // when do we need to add the loop variable back?
183
+
184
+ // the loop variable is referenced for the current loop
185
+ elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
186
+ $this->addLoopToCurrent();
187
+ }
188
+
189
+ // block reference
190
+ elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) {
191
+ $this->addLoopToCurrent();
192
+ }
193
+
194
+ // include without the only attribute
195
+ elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
196
+ $this->addLoopToAll();
197
+ }
198
+
199
+ // the loop variable is referenced via an attribute
200
+ elseif ($node instanceof Twig_Node_Expression_GetAttr
201
+ && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
202
+ || 'parent' === $node->getNode('attribute')->getAttribute('value')
203
+ )
204
+ && (true === $this->loops[0]->getAttribute('with_loop')
205
+ || ($node->getNode('node') instanceof Twig_Node_Expression_Name
206
+ && 'loop' === $node->getNode('node')->getAttribute('name')
207
+ )
208
+ )
209
+ ) {
210
+ $this->addLoopToAll();
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
216
+ *
217
+ * @param Twig_NodeInterface $node A Node
218
+ * @param Twig_Environment $env The current Twig environment
219
+ */
220
+ protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
221
+ {
222
+ if ($node instanceof Twig_Node_For) {
223
+ array_shift($this->loops);
224
+ }
225
+ }
226
+
227
+ protected function addLoopToCurrent()
228
+ {
229
+ $this->loops[0]->setAttribute('with_loop', true);
230
+ }
231
+
232
+ protected function addLoopToAll()
233
+ {
234
+ foreach ($this->loops as $loop) {
235
+ $loop->setAttribute('with_loop', true);
236
+ }
237
+ }
238
+
239
+ /**
240
+ * {@inheritdoc}
241
+ */
242
+ public function getPriority()
243
+ {
244
+ return 255;
245
+ }
246
+ }
classes/Twig/NodeVisitor/SafeAnalysis.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
4
+ {
5
+ protected $data = array();
6
+ protected $safeVars = array();
7
+
8
+ public function setSafeVars($safeVars)
9
+ {
10
+ $this->safeVars = $safeVars;
11
+ }
12
+
13
+ public function getSafe(Twig_NodeInterface $node)
14
+ {
15
+ $hash = spl_object_hash($node);
16
+ if (!isset($this->data[$hash])) {
17
+ return;
18
+ }
19
+
20
+ foreach ($this->data[$hash] as $bucket) {
21
+ if ($bucket['key'] !== $node) {
22
+ continue;
23
+ }
24
+
25
+ if (in_array('html_attr', $bucket['value'])) {
26
+ $bucket['value'][] = 'html';
27
+ }
28
+
29
+ return $bucket['value'];
30
+ }
31
+ }
32
+
33
+ protected function setSafe(Twig_NodeInterface $node, array $safe)
34
+ {
35
+ $hash = spl_object_hash($node);
36
+ if (isset($this->data[$hash])) {
37
+ foreach ($this->data[$hash] as &$bucket) {
38
+ if ($bucket['key'] === $node) {
39
+ $bucket['value'] = $safe;
40
+
41
+ return;
42
+ }
43
+ }
44
+ }
45
+ $this->data[$hash][] = array(
46
+ 'key' => $node,
47
+ 'value' => $safe,
48
+ );
49
+ }
50
+
51
+ public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
52
+ {
53
+ return $node;
54
+ }
55
+
56
+ public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
57
+ {
58
+ if ($node instanceof Twig_Node_Expression_Constant) {
59
+ // constants are marked safe for all
60
+ $this->setSafe($node, array('all'));
61
+ } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
62
+ // blocks are safe by definition
63
+ $this->setSafe($node, array('all'));
64
+ } elseif ($node instanceof Twig_Node_Expression_Parent) {
65
+ // parent block is safe by definition
66
+ $this->setSafe($node, array('all'));
67
+ } elseif ($node instanceof Twig_Node_Expression_Conditional) {
68
+ // intersect safeness of both operands
69
+ $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
70
+ $this->setSafe($node, $safe);
71
+ } elseif ($node instanceof Twig_Node_Expression_Filter) {
72
+ // filter expression is safe when the filter is safe
73
+ $name = $node->getNode('filter')->getAttribute('value');
74
+ $args = $node->getNode('arguments');
75
+ if (false !== $filter = $env->getFilter($name)) {
76
+ $safe = $filter->getSafe($args);
77
+ if (null === $safe) {
78
+ $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety());
79
+ }
80
+ $this->setSafe($node, $safe);
81
+ } else {
82
+ $this->setSafe($node, array());
83
+ }
84
+ } elseif ($node instanceof Twig_Node_Expression_Function) {
85
+ // function expression is safe when the function is safe
86
+ $name = $node->getAttribute('name');
87
+ $args = $node->getNode('arguments');
88
+ $function = $env->getFunction($name);
89
+ if (false !== $function) {
90
+ $this->setSafe($node, $function->getSafe($args));
91
+ } else {
92
+ $this->setSafe($node, array());
93
+ }
94
+ } elseif ($node instanceof Twig_Node_Expression_MethodCall) {
95
+ if ($node->getAttribute('safe')) {
96
+ $this->setSafe($node, array('all'));
97
+ } else {
98
+ $this->setSafe($node, array());
99
+ }
100
+ } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
101
+ $name = $node->getNode('node')->getAttribute('name');
102
+ // attributes on template instances are safe
103
+ if ('_self' == $name || in_array($name, $this->safeVars)) {
104
+ $this->setSafe($node, array('all'));
105
+ } else {
106
+ $this->setSafe($node, array());
107
+ }
108
+ } else {
109
+ $this->setSafe($node, array());
110
+ }
111
+
112
+ return $node;
113
+ }
114
+
115
+ protected function intersectSafe(array $a = null, array $b = null)
116
+ {
117
+ if (null === $a || null === $b) {
118
+ return array();
119
+ }
120
+
121
+ if (in_array('all', $a)) {
122
+ return $b;
123
+ }
124
+
125
+ if (in_array('all', $b)) {
126
+ return $a;
127
+ }
128
+
129
+ return array_intersect($a, $b);
130
+ }
131
+
132
+ /**
133
+ * {@inheritdoc}
134
+ */
135
+ public function getPriority()
136
+ {
137
+ return 0;
138
+ }
139
+ }
classes/Twig/NodeVisitor/Sandbox.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig_NodeVisitor_Sandbox implements sandboxing.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
18
+ {
19
+ protected $inAModule = false;
20
+ protected $tags;
21
+ protected $filters;
22
+ protected $functions;
23
+
24
+ /**
25
+ * Called before child nodes are visited.
26
+ *
27
+ * @param Twig_NodeInterface $node The node to visit
28
+ * @param Twig_Environment $env The Twig environment instance
29
+ *
30
+ * @return Twig_NodeInterface The modified node
31
+ */
32
+ public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
33
+ {
34
+ if ($node instanceof Twig_Node_Module) {
35
+ $this->inAModule = true;
36
+ $this->tags = array();
37
+ $this->filters = array();
38
+ $this->functions = array();
39
+
40
+ return $node;
41
+ } elseif ($this->inAModule) {
42
+ // look for tags
43
+ if ($node->getNodeTag()) {
44
+ $this->tags[] = $node->getNodeTag();
45
+ }
46
+
47
+ // look for filters
48
+ if ($node instanceof Twig_Node_Expression_Filter) {
49
+ $this->filters[] = $node->getNode('filter')->getAttribute('value');
50
+ }
51
+
52
+ // look for functions
53
+ if ($node instanceof Twig_Node_Expression_Function) {
54
+ $this->functions[] = $node->getAttribute('name');
55
+ }
56
+
57
+ // wrap print to check __toString() calls
58
+ if ($node instanceof Twig_Node_Print) {
59
+ return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getLine(), $node->getNodeTag());
60
+ }
61
+ }
62
+
63
+ return $node;
64
+ }
65
+
66
+ /**
67
+ * Called after child nodes are visited.
68
+ *
69
+ * @param Twig_NodeInterface $node The node to visit
70
+ * @param Twig_Environment $env The Twig environment instance
71
+ *
72
+ * @return Twig_NodeInterface The modified node
73
+ */
74
+ public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
75
+ {
76
+ if ($node instanceof Twig_Node_Module) {
77
+ $this->inAModule = false;
78
+
79
+ return new Twig_Node_SandboxedModule($node, array_unique($this->filters), array_unique($this->tags), array_unique($this->functions));
80
+ }
81
+
82
+ return $node;
83
+ }
84
+
85
+ /**
86
+ * {@inheritdoc}
87
+ */
88
+ public function getPriority()
89
+ {
90
+ return 0;
91
+ }
92
+ }
classes/Twig/NodeVisitorInterface.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ interface Twig_NodeVisitorInterface
18
+ {
19
+ /**
20
+ * Called before child nodes are visited.
21
+ *
22
+ * @param Twig_NodeInterface $node The node to visit
23
+ * @param Twig_Environment $env The Twig environment instance
24
+ *
25
+ * @return Twig_NodeInterface The modified node
26
+ */
27
+ public function enterNode(Twig_NodeInterface $node, Twig_Environment $env);
28
+
29
+ /**
30
+ * Called after child nodes are visited.
31
+ *
32
+ * @param Twig_NodeInterface $node The node to visit
33
+ * @param Twig_Environment $env The Twig environment instance
34
+ *
35
+ * @return Twig_NodeInterface|false The modified node or false if the node must be removed
36
+ */
37
+ public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
38
+
39
+ /**
40
+ * Returns the priority for this visitor.
41
+ *
42
+ * Priority should be between -10 and 10 (0 is the default).
43
+ *
44
+ * @return int The priority level
45
+ */
46
+ public function getPriority();
47
+ }
classes/Twig/Parser.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Default parser implementation.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Parser implements Twig_ParserInterface
19
+ {
20
+ protected $stack = array();
21
+ protected $stream;
22
+ protected $parent;
23
+ protected $handlers;
24
+ protected $visitors;
25
+ protected $expressionParser;
26
+ protected $blocks;
27
+ protected $blockStack;
28
+ protected $macros;
29
+ protected $env;
30
+ protected $reservedMacroNames;
31
+ protected $importedSymbols;
32
+ protected $traits;
33
+ protected $embeddedTemplates = array();
34
+
35
+ /**
36
+ * Constructor.
37
+ *
38
+ * @param Twig_Environment $env A Twig_Environment instance
39
+ */
40
+ public function __construct(Twig_Environment $env)
41
+ {
42
+ $this->env = $env;
43
+ }
44
+
45
+ public function getEnvironment()
46
+ {
47
+ return $this->env;
48
+ }
49
+
50
+ public function getVarName()
51
+ {
52
+ return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
53
+ }
54
+
55
+ public function getFilename()
56
+ {
57
+ return $this->stream->getFilename();
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
64
+ {
65
+ // push all variables into the stack to keep the current state of the parser
66
+ $vars = get_object_vars($this);
67
+ unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser']);
68
+ $this->stack[] = $vars;
69
+
70
+ // tag handlers
71
+ if (null === $this->handlers) {
72
+ $this->handlers = $this->env->getTokenParsers();
73
+ $this->handlers->setParser($this);
74
+ }
75
+
76
+ // node visitors
77
+ if (null === $this->visitors) {
78
+ $this->visitors = $this->env->getNodeVisitors();
79
+ }
80
+
81
+ if (null === $this->expressionParser) {
82
+ $this->expressionParser = new Twig_ExpressionParser($this, $this->env->getUnaryOperators(), $this->env->getBinaryOperators());
83
+ }
84
+
85
+ $this->stream = $stream;
86
+ $this->parent = null;
87
+ $this->blocks = array();
88
+ $this->macros = array();
89
+ $this->traits = array();
90
+ $this->blockStack = array();
91
+ $this->importedSymbols = array(array());
92
+ $this->embeddedTemplates = array();
93
+
94
+ try {
95
+ $body = $this->subparse($test, $dropNeedle);
96
+
97
+ if (null !== $this->parent) {
98
+ if (null === $body = $this->filterBodyNodes($body)) {
99
+ $body = new Twig_Node();
100
+ }
101
+ }
102
+ } catch (Twig_Error_Syntax $e) {
103
+ if (!$e->getTemplateFile()) {
104
+ $e->setTemplateFile($this->getFilename());
105
+ }
106
+
107
+ if (!$e->getTemplateLine()) {
108
+ $e->setTemplateLine($this->stream->getCurrent()->getLine());
109
+ }
110
+
111
+ throw $e;
112
+ }
113
+
114
+ $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->getFilename());
115
+
116
+ $traverser = new Twig_NodeTraverser($this->env, $this->visitors);
117
+
118
+ $node = $traverser->traverse($node);
119
+
120
+ // restore previous stack so previous parse() call can resume working
121
+ foreach (array_pop($this->stack) as $key => $val) {
122
+ $this->$key = $val;
123
+ }
124
+
125
+ return $node;
126
+ }
127
+
128
+ public function subparse($test, $dropNeedle = false)
129
+ {
130
+ $lineno = $this->getCurrentToken()->getLine();
131
+ $rv = array();
132
+ while (!$this->stream->isEOF()) {
133
+ switch ($this->getCurrentToken()->getType()) {
134
+ case Twig_Token::TEXT_TYPE:
135
+ $token = $this->stream->next();
136
+ $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine());
137
+ break;
138
+
139
+ case Twig_Token::VAR_START_TYPE:
140
+ $token = $this->stream->next();
141
+ $expr = $this->expressionParser->parseExpression();
142
+ $this->stream->expect(Twig_Token::VAR_END_TYPE);
143
+ $rv[] = new Twig_Node_Print($expr, $token->getLine());
144
+ break;
145
+
146
+ case Twig_Token::BLOCK_START_TYPE:
147
+ $this->stream->next();
148
+ $token = $this->getCurrentToken();
149
+
150
+ if ($token->getType() !== Twig_Token::NAME_TYPE) {
151
+ throw new Twig_Error_Syntax('A block must start with a tag name', $token->getLine(), $this->getFilename());
152
+ }
153
+
154
+ if (null !== $test && call_user_func($test, $token)) {
155
+ if ($dropNeedle) {
156
+ $this->stream->next();
157
+ }
158
+
159
+ if (1 === count($rv)) {
160
+ return $rv[0];
161
+ }
162
+
163
+ return new Twig_Node($rv, array(), $lineno);
164
+ }
165
+
166
+ $subparser = $this->handlers->getTokenParser($token->getValue());
167
+ if (null === $subparser) {
168
+ if (null !== $test) {
169
+ $error = sprintf('Unexpected tag name "%s"', $token->getValue());
170
+ if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
171
+ $error .= sprintf(' (expecting closing tag for the "%s" tag defined near line %s)', $test[0]->getTag(), $lineno);
172
+ }
173
+
174
+ throw new Twig_Error_Syntax($error, $token->getLine(), $this->getFilename());
175
+ }
176
+
177
+ $message = sprintf('Unknown tag name "%s"', $token->getValue());
178
+ if ($alternatives = $this->env->computeAlternatives($token->getValue(), array_keys($this->env->getTags()))) {
179
+ $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
180
+ }
181
+
182
+ throw new Twig_Error_Syntax($message, $token->getLine(), $this->getFilename());
183
+ }
184
+
185
+ $this->stream->next();
186
+
187
+ $node = $subparser->parse($token);
188
+ if (null !== $node) {
189
+ $rv[] = $node;
190
+ }
191
+ break;
192
+
193
+ default:
194
+ throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename());
195
+ }
196
+ }
197
+
198
+ if (1 === count($rv)) {
199
+ return $rv[0];
200
+ }
201
+
202
+ return new Twig_Node($rv, array(), $lineno);
203
+ }
204
+
205
+ public function addHandler($name, $class)
206
+ {
207
+ $this->handlers[$name] = $class;
208
+ }
209
+
210
+ public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
211
+ {
212
+ $this->visitors[] = $visitor;
213
+ }
214
+
215
+ public function getBlockStack()
216
+ {
217
+ return $this->blockStack;
218
+ }
219
+
220
+ public function peekBlockStack()
221
+ {
222
+ return $this->blockStack[count($this->blockStack) - 1];
223
+ }
224
+
225
+ public function popBlockStack()
226
+ {
227
+ array_pop($this->blockStack);
228
+ }
229
+
230
+ public function pushBlockStack($name)
231
+ {
232
+ $this->blockStack[] = $name;
233
+ }
234
+
235
+ public function hasBlock($name)
236
+ {
237
+ return isset($this->blocks[$name]);
238
+ }
239
+
240
+ public function getBlock($name)
241
+ {
242
+ return $this->blocks[$name];
243
+ }
244
+
245
+ public function setBlock($name, Twig_Node_Block $value)
246
+ {
247
+ $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getLine());
248
+ }
249
+
250
+ public function hasMacro($name)
251
+ {
252
+ return isset($this->macros[$name]);
253
+ }
254
+
255
+ public function setMacro($name, Twig_Node_Macro $node)
256
+ {
257
+ if (null === $this->reservedMacroNames) {
258
+ $this->reservedMacroNames = array();
259
+ $r = new ReflectionClass($this->env->getBaseTemplateClass());
260
+ foreach ($r->getMethods() as $method) {
261
+ $this->reservedMacroNames[] = $method->getName();
262
+ }
263
+ }
264
+
265
+ if (in_array($name, $this->reservedMacroNames)) {
266
+ throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine(), $this->getFilename());
267
+ }
268
+
269
+ $this->macros[$name] = $node;
270
+ }
271
+
272
+ public function addTrait($trait)
273
+ {
274
+ $this->traits[] = $trait;
275
+ }
276
+
277
+ public function hasTraits()
278
+ {
279
+ return count($this->traits) > 0;
280
+ }
281
+
282
+ public function embedTemplate(Twig_Node_Module $template)
283
+ {
284
+ $template->setIndex(mt_rand());
285
+
286
+ $this->embeddedTemplates[] = $template;
287
+ }
288
+
289
+ public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null)
290
+ {
291
+ $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node);
292
+ }
293
+
294
+ public function getImportedSymbol($type, $alias)
295
+ {
296
+ foreach ($this->importedSymbols as $functions) {
297
+ if (isset($functions[$type][$alias])) {
298
+ return $functions[$type][$alias];
299
+ }
300
+ }
301
+ }
302
+
303
+ public function isMainScope()
304
+ {
305
+ return 1 === count($this->importedSymbols);
306
+ }
307
+
308
+ public function pushLocalScope()
309
+ {
310
+ array_unshift($this->importedSymbols, array());
311
+ }
312
+
313
+ public function popLocalScope()
314
+ {
315
+ array_shift($this->importedSymbols);
316
+ }
317
+
318
+ /**
319
+ * Gets the expression parser.
320
+ *
321
+ * @return Twig_ExpressionParser The expression parser
322
+ */
323
+ public function getExpressionParser()
324
+ {
325
+ return $this->expressionParser;
326
+ }
327
+
328
+ public function getParent()
329
+ {
330
+ return $this->parent;
331
+ }
332
+
333
+ public function setParent($parent)
334
+ {
335
+ $this->parent = $parent;
336
+ }
337
+
338
+ /**
339
+ * Gets the token stream.
340
+ *
341
+ * @return Twig_TokenStream The token stream
342
+ */
343
+ public function getStream()
344
+ {
345
+ return $this->stream;
346
+ }
347
+
348
+ /**
349
+ * Gets the current token.
350
+ *
351
+ * @return Twig_Token The current token
352
+ */
353
+ public function getCurrentToken()
354
+ {
355
+ return $this->stream->getCurrent();
356
+ }
357
+
358
+ protected function filterBodyNodes(Twig_NodeInterface $node)
359
+ {
360
+ // check that the body does not contain non-empty output nodes
361
+ if (
362
+ ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data')))
363
+ ||
364
+ (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
365
+ ) {
366
+ if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
367
+ throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->getFilename());
368
+ }
369
+
370
+ throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->getFilename());
371
+ }
372
+
373
+ // bypass "set" nodes as they "capture" the output
374
+ if ($node instanceof Twig_Node_Set) {
375
+ return $node;
376
+ }
377
+
378
+ if ($node instanceof Twig_NodeOutputInterface) {
379
+ return;
380
+ }
381
+
382
+ foreach ($node as $k => $n) {
383
+ if (null !== $n && null === $this->filterBodyNodes($n)) {
384
+ $node->removeNode($k);
385
+ }
386
+ }
387
+
388
+ return $node;
389
+ }
390
+ }
classes/Twig/ParserInterface.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface implemented by parser classes.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ *
17
+ * @deprecated since 1.12 (to be removed in 3.0)
18
+ */
19
+ interface Twig_ParserInterface
20
+ {
21
+ /**
22
+ * Converts a token stream to a node tree.
23
+ *
24
+ * @param Twig_TokenStream $stream A token stream instance
25
+ *
26
+ * @return Twig_Node_Module A node tree
27
+ *
28
+ * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
29
+ */
30
+ public function parse(Twig_TokenStream $stream);
31
+ }
classes/Twig/Sandbox/SecurityError.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Exception thrown when a security error occurs at runtime.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Sandbox_SecurityError extends Twig_Error
18
+ {
19
+ }
classes/Twig/Sandbox/SecurityPolicy.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a security policy which need to be enforced when sandbox mode is enabled.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface
18
+ {
19
+ protected $allowedTags;
20
+ protected $allowedFilters;
21
+ protected $allowedMethods;
22
+ protected $allowedProperties;
23
+ protected $allowedFunctions;
24
+
25
+ public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array(), array $allowedFunctions = array())
26
+ {
27
+ $this->allowedTags = $allowedTags;
28
+ $this->allowedFilters = $allowedFilters;
29
+ $this->setAllowedMethods($allowedMethods);
30
+ $this->allowedProperties = $allowedProperties;
31
+ $this->allowedFunctions = $allowedFunctions;
32
+ }
33
+
34
+ public function setAllowedTags(array $tags)
35
+ {
36
+ $this->allowedTags = $tags;
37
+ }
38
+
39
+ public function setAllowedFilters(array $filters)
40
+ {
41
+ $this->allowedFilters = $filters;
42
+ }
43
+
44
+ public function setAllowedMethods(array $methods)
45
+ {
46
+ $this->allowedMethods = array();
47
+ foreach ($methods as $class => $m) {
48
+ $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : array($m));
49
+ }
50
+ }
51
+
52
+ public function setAllowedProperties(array $properties)
53
+ {
54
+ $this->allowedProperties = $properties;
55
+ }
56
+
57
+ public function setAllowedFunctions(array $functions)
58
+ {
59
+ $this->allowedFunctions = $functions;
60
+ }
61
+
62
+ public function checkSecurity($tags, $filters, $functions)
63
+ {
64
+ foreach ($tags as $tag) {
65
+ if (!in_array($tag, $this->allowedTags)) {
66
+ throw new Twig_Sandbox_SecurityError(sprintf('Tag "%s" is not allowed.', $tag));
67
+ }
68
+ }
69
+
70
+ foreach ($filters as $filter) {
71
+ if (!in_array($filter, $this->allowedFilters)) {
72
+ throw new Twig_Sandbox_SecurityError(sprintf('Filter "%s" is not allowed.', $filter));
73
+ }
74
+ }
75
+
76
+ foreach ($functions as $function) {
77
+ if (!in_array($function, $this->allowedFunctions)) {
78
+ throw new Twig_Sandbox_SecurityError(sprintf('Function "%s" is not allowed.', $function));
79
+ }
80
+ }
81
+ }
82
+
83
+ public function checkMethodAllowed($obj, $method)
84
+ {
85
+ if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) {
86
+ return true;
87
+ }
88
+
89
+ $allowed = false;
90
+ $method = strtolower($method);
91
+ foreach ($this->allowedMethods as $class => $methods) {
92
+ if ($obj instanceof $class) {
93
+ $allowed = in_array($method, $methods);
94
+
95
+ break;
96
+ }
97
+ }
98
+
99
+ if (!$allowed) {
100
+ throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj)));
101
+ }
102
+ }
103
+
104
+ public function checkPropertyAllowed($obj, $property)
105
+ {
106
+ $allowed = false;
107
+ foreach ($this->allowedProperties as $class => $properties) {
108
+ if ($obj instanceof $class) {
109
+ $allowed = in_array($property, is_array($properties) ? $properties : array($properties));
110
+
111
+ break;
112
+ }
113
+ }
114
+
115
+ if (!$allowed) {
116
+ throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, get_class($obj)));
117
+ }
118
+ }
119
+ }
classes/Twig/Sandbox/SecurityPolicyInterface.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interfaces that all security policy classes must implements.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ interface Twig_Sandbox_SecurityPolicyInterface
18
+ {
19
+ public function checkSecurity($tags, $filters, $functions);
20
+
21
+ public function checkMethodAllowed($obj, $method);
22
+
23
+ public function checkPropertyAllowed($obj, $method);
24
+ }
classes/Twig/SimpleFilter.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009-2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template filter.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_SimpleFilter
18
+ {
19
+ protected $name;
20
+ protected $callable;
21
+ protected $options;
22
+ protected $arguments = array();
23
+
24
+ public function __construct($name, $callable, array $options = array())
25
+ {
26
+ $this->name = $name;
27
+ $this->callable = $callable;
28
+ $this->options = array_merge(array(
29
+ 'needs_environment' => false,
30
+ 'needs_context' => false,
31
+ 'is_safe' => null,
32
+ 'is_safe_callback' => null,
33
+ 'pre_escape' => null,
34
+ 'preserves_safety' => null,
35
+ 'node_class' => 'Twig_Node_Expression_Filter',
36
+ ), $options);
37
+ }
38
+
39
+ public function getName()
40
+ {
41
+ return $this->name;
42
+ }
43
+
44
+ public function getCallable()
45
+ {
46
+ return $this->callable;
47
+ }
48
+
49
+ public function getNodeClass()
50
+ {
51
+ return $this->options['node_class'];
52
+ }
53
+
54
+ public function setArguments($arguments)
55
+ {
56
+ $this->arguments = $arguments;
57
+ }
58
+
59
+ public function getArguments()
60
+ {
61
+ return $this->arguments;
62
+ }
63
+
64
+ public function needsEnvironment()
65
+ {
66
+ return $this->options['needs_environment'];
67
+ }
68
+
69
+ public function needsContext()
70
+ {
71
+ return $this->options['needs_context'];
72
+ }
73
+
74
+ public function getSafe(Twig_Node $filterArgs)
75
+ {
76
+ if (null !== $this->options['is_safe']) {
77
+ return $this->options['is_safe'];
78
+ }
79
+
80
+ if (null !== $this->options['is_safe_callback']) {
81
+ return call_user_func($this->options['is_safe_callback'], $filterArgs);
82
+ }
83
+ }
84
+
85
+ public function getPreservesSafety()
86
+ {
87
+ return $this->options['preserves_safety'];
88
+ }
89
+
90
+ public function getPreEscape()
91
+ {
92
+ return $this->options['pre_escape'];
93
+ }
94
+ }
classes/Twig/SimpleFunction.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010-2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template function.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_SimpleFunction
18
+ {
19
+ protected $name;
20
+ protected $callable;
21
+ protected $options;
22
+ protected $arguments = array();
23
+
24
+ public function __construct($name, $callable, array $options = array())
25
+ {
26
+ $this->name = $name;
27
+ $this->callable = $callable;
28
+ $this->options = array_merge(array(
29
+ 'needs_environment' => false,
30
+ 'needs_context' => false,
31
+ 'is_safe' => null,
32
+ 'is_safe_callback' => null,
33
+ 'node_class' => 'Twig_Node_Expression_Function',
34
+ ), $options);
35
+ }
36
+
37
+ public function getName()
38
+ {
39
+ return $this->name;
40
+ }
41
+
42
+ public function getCallable()
43
+ {
44
+ return $this->callable;
45
+ }
46
+
47
+ public function getNodeClass()
48
+ {
49
+ return $this->options['node_class'];
50
+ }
51
+
52
+ public function setArguments($arguments)
53
+ {
54
+ $this->arguments = $arguments;
55
+ }
56
+
57
+ public function getArguments()
58
+ {
59
+ return $this->arguments;
60
+ }
61
+
62
+ public function needsEnvironment()
63
+ {
64
+ return $this->options['needs_environment'];
65
+ }
66
+
67
+ public function needsContext()
68
+ {
69
+ return $this->options['needs_context'];
70
+ }
71
+
72
+ public function getSafe(Twig_Node $functionArgs)
73
+ {
74
+ if (null !== $this->options['is_safe']) {
75
+ return $this->options['is_safe'];
76
+ }
77
+
78
+ if (null !== $this->options['is_safe_callback']) {
79
+ return call_user_func($this->options['is_safe_callback'], $functionArgs);
80
+ }
81
+
82
+ return array();
83
+ }
84
+ }
classes/Twig/SimpleTest.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010-2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template test.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ class Twig_SimpleTest
18
+ {
19
+ protected $name;
20
+ protected $callable;
21
+ protected $options;
22
+
23
+ public function __construct($name, $callable, array $options = array())
24
+ {
25
+ $this->name = $name;
26
+ $this->callable = $callable;
27
+ $this->options = array_merge(array(
28
+ 'node_class' => 'Twig_Node_Expression_Test',
29
+ ), $options);
30
+ }
31
+
32
+ public function getName()
33
+ {
34
+ return $this->name;
35
+ }
36
+
37
+ public function getCallable()
38
+ {
39
+ return $this->callable;
40
+ }
41
+
42
+ public function getNodeClass()
43
+ {
44
+ return $this->options['node_class'];
45
+ }
46
+ }
classes/Twig/Template.php ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Default base class for compiled templates.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ abstract class Twig_Template implements Twig_TemplateInterface
19
+ {
20
+ protected static $cache = array();
21
+
22
+ protected $parent;
23
+ protected $parents;
24
+ protected $env;
25
+ protected $blocks;
26
+ protected $traits;
27
+
28
+ /**
29
+ * Constructor.
30
+ *
31
+ * @param Twig_Environment $env A Twig_Environment instance
32
+ */
33
+ public function __construct(Twig_Environment $env)
34
+ {
35
+ $this->env = $env;
36
+ $this->blocks = array();
37
+ $this->traits = array();
38
+ }
39
+
40
+ /**
41
+ * Returns the template name.
42
+ *
43
+ * @return string The template name
44
+ */
45
+ abstract public function getTemplateName();
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ public function getEnvironment()
51
+ {
52
+ return $this->env;
53
+ }
54
+
55
+ /**
56
+ * Returns the parent template.
57
+ *
58
+ * This method is for internal use only and should never be called
59
+ * directly.
60
+ *
61
+ * @return Twig_TemplateInterface|false The parent template or false if there is no parent
62
+ */
63
+ public function getParent(array $context)
64
+ {
65
+ if (null !== $this->parent) {
66
+ return $this->parent;
67
+ }
68
+
69
+ $parent = $this->doGetParent($context);
70
+ if (false === $parent) {
71
+ return false;
72
+ } elseif ($parent instanceof Twig_Template) {
73
+ $name = $parent->getTemplateName();
74
+ $this->parents[$name] = $parent;
75
+ $parent = $name;
76
+ } elseif (!isset($this->parents[$parent])) {
77
+ $this->parents[$parent] = $this->env->loadTemplate($parent);
78
+ }
79
+
80
+ return $this->parents[$parent];
81
+ }
82
+
83
+ protected function doGetParent(array $context)
84
+ {
85
+ return false;
86
+ }
87
+
88
+ public function isTraitable()
89
+ {
90
+ return true;
91
+ }
92
+
93
+ /**
94
+ * Displays a parent block.
95
+ *
96
+ * This method is for internal use only and should never be called
97
+ * directly.
98
+ *
99
+ * @param string $name The block name to display from the parent
100
+ * @param array $context The context
101
+ * @param array $blocks The current set of blocks
102
+ */
103
+ public function displayParentBlock($name, array $context, array $blocks = array())
104
+ {
105
+ $name = (string) $name;
106
+
107
+ if (isset($this->traits[$name])) {
108
+ $this->traits[$name][0]->displayBlock($name, $context, $blocks, false);
109
+ } elseif (false !== $parent = $this->getParent($context)) {
110
+ $parent->displayBlock($name, $context, $blocks, false);
111
+ } else {
112
+ throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName());
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Displays a block.
118
+ *
119
+ * This method is for internal use only and should never be called
120
+ * directly.
121
+ *
122
+ * @param string $name The block name to display
123
+ * @param array $context The context
124
+ * @param array $blocks The current set of blocks
125
+ * @param bool $useBlocks Whether to use the current set of blocks
126
+ */
127
+ public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
128
+ {
129
+ $name = (string) $name;
130
+
131
+ if ($useBlocks && isset($blocks[$name])) {
132
+ $template = $blocks[$name][0];
133
+ $block = $blocks[$name][1];
134
+ } elseif (isset($this->blocks[$name])) {
135
+ $template = $this->blocks[$name][0];
136
+ $block = $this->blocks[$name][1];
137
+ } else {
138
+ $template = null;
139
+ $block = null;
140
+ }
141
+
142
+ if (null !== $template) {
143
+ try {
144
+ $template->$block($context, $blocks);
145
+ } catch (Twig_Error $e) {
146
+ throw $e;
147
+ } catch (Exception $e) {
148
+ throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
149
+ }
150
+ } elseif (false !== $parent = $this->getParent($context)) {
151
+ $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Renders a parent block.
157
+ *
158
+ * This method is for internal use only and should never be called
159
+ * directly.
160
+ *
161
+ * @param string $name The block name to render from the parent
162
+ * @param array $context The context
163
+ * @param array $blocks The current set of blocks
164
+ *
165
+ * @return string The rendered block
166
+ */
167
+ public function renderParentBlock($name, array $context, array $blocks = array())
168
+ {
169
+ ob_start();
170
+ $this->displayParentBlock($name, $context, $blocks);
171
+
172
+ return ob_get_clean();
173
+ }
174
+
175
+ /**
176
+ * Renders a block.
177
+ *
178
+ * This method is for internal use only and should never be called
179
+ * directly.
180
+ *
181
+ * @param string $name The block name to render
182
+ * @param array $context The context
183
+ * @param array $blocks The current set of blocks
184
+ * @param bool $useBlocks Whether to use the current set of blocks
185
+ *
186
+ * @return string The rendered block
187
+ */
188
+ public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
189
+ {
190
+ ob_start();
191
+ $this->displayBlock($name, $context, $blocks, $useBlocks);
192
+
193
+ return ob_get_clean();
194
+ }
195
+
196
+ /**
197
+ * Returns whether a block exists or not.
198
+ *
199
+ * This method is for internal use only and should never be called
200
+ * directly.
201
+ *
202
+ * This method does only return blocks defined in the current template
203
+ * or defined in "used" traits.
204
+ *
205
+ * It does not return blocks from parent templates as the parent
206
+ * template name can be dynamic, which is only known based on the
207
+ * current context.
208
+ *
209
+ * @param string $name The block name
210
+ *
211
+ * @return bool true if the block exists, false otherwise
212
+ */
213
+ public function hasBlock($name)
214
+ {
215
+ return isset($this->blocks[(string) $name]);
216
+ }
217
+
218
+ /**
219
+ * Returns all block names.
220
+ *
221
+ * This method is for internal use only and should never be called
222
+ * directly.
223
+ *
224
+ * @return array An array of block names
225
+ *
226
+ * @see hasBlock
227
+ */
228
+ public function getBlockNames()
229
+ {
230
+ return array_keys($this->blocks);
231
+ }
232
+
233
+ /**
234
+ * Returns all blocks.
235
+ *
236
+ * This method is for internal use only and should never be called
237
+ * directly.
238
+ *
239
+ * @return array An array of blocks
240
+ *
241
+ * @see hasBlock
242
+ */
243
+ public function getBlocks()
244
+ {
245
+ return $this->blocks;
246
+ }
247
+
248
+ /**
249
+ * {@inheritdoc}
250
+ */
251
+ public function display(array $context, array $blocks = array())
252
+ {
253
+ $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks));
254
+ }
255
+
256
+ /**
257
+ * {@inheritdoc}
258
+ */
259
+ public function render(array $context)
260
+ {
261
+ $level = ob_get_level();
262
+ ob_start();
263
+ try {
264
+ $this->display($context);
265
+ } catch (Exception $e) {
266
+ while (ob_get_level() > $level) {
267
+ ob_end_clean();
268
+ }
269
+
270
+ throw $e;
271
+ }
272
+
273
+ return ob_get_clean();
274
+ }
275
+
276
+ protected function displayWithErrorHandling(array $context, array $blocks = array())
277
+ {
278
+ try {
279
+ $this->doDisplay($context, $blocks);
280
+ } catch (Twig_Error $e) {
281
+ if (!$e->getTemplateFile()) {
282
+ $e->setTemplateFile($this->getTemplateName());
283
+ }
284
+
285
+ // this is mostly useful for Twig_Error_Loader exceptions
286
+ // see Twig_Error_Loader
287
+ if (false === $e->getTemplateLine()) {
288
+ $e->setTemplateLine(-1);
289
+ $e->guess();
290
+ }
291
+
292
+ throw $e;
293
+ } catch (Exception $e) {
294
+ throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e);
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Auto-generated method to display the template with the given context.
300
+ *
301
+ * @param array $context An array of parameters to pass to the template
302
+ * @param array $blocks An array of blocks to pass to the template
303
+ */
304
+ abstract protected function doDisplay(array $context, array $blocks = array());
305
+
306
+ /**
307
+ * Returns a variable from the context.
308
+ *
309
+ * This method is for internal use only and should never be called
310
+ * directly.
311
+ *
312
+ * This method should not be overridden in a sub-class as this is an
313
+ * implementation detail that has been introduced to optimize variable
314
+ * access for versions of PHP before 5.4. This is not a way to override
315
+ * the way to get a variable value.
316
+ *
317
+ * @param array $context The context
318
+ * @param string $item The variable to return from the context
319
+ * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not
320
+ *
321
+ * @return The content of the context variable
322
+ *
323
+ * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
324
+ */
325
+ final protected function getContext($context, $item, $ignoreStrictCheck = false)
326
+ {
327
+ if (!array_key_exists($item, $context)) {
328
+ if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
329
+ return;
330
+ }
331
+
332
+ throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName());
333
+ }
334
+
335
+ return $context[$item];
336
+ }
337
+
338
+ /**
339
+ * Returns the attribute value for a given array/object.
340
+ *
341
+ * @param mixed $object The object or array from where to get the item
342
+ * @param mixed $item The item to get from the array or object
343
+ * @param array $arguments An array of arguments to pass if the item is an object method
344
+ * @param string $type The type of attribute (@see Twig_Template constants)
345
+ * @param bool $isDefinedTest Whether this is only a defined check
346
+ * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not
347
+ *
348
+ * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
349
+ *
350
+ * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
351
+ */
352
+ protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
353
+ {
354
+ // array
355
+ if (Twig_Template::METHOD_CALL !== $type) {
356
+ $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
357
+
358
+ if ((is_array($object) && array_key_exists($arrayItem, $object))
359
+ || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
360
+ ) {
361
+ if ($isDefinedTest) {
362
+ return true;
363
+ }
364
+
365
+ return $object[$arrayItem];
366
+ }
367
+
368
+ if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) {
369
+ if ($isDefinedTest) {
370
+ return false;
371
+ }
372
+
373
+ if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
374
+ return;
375
+ }
376
+
377
+ if ($object instanceof ArrayAccess) {
378
+ $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist', $arrayItem, get_class($object));
379
+ } elseif (is_object($object)) {
380
+ $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object));
381
+ } elseif (is_array($object)) {
382
+ $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
383
+ } elseif (Twig_Template::ARRAY_CALL === $type) {
384
+ $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
385
+ } else {
386
+ $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
387
+ }
388
+
389
+ throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
390
+ }
391
+ }
392
+
393
+ if (!is_object($object)) {
394
+ if ($isDefinedTest) {
395
+ return false;
396
+ }
397
+
398
+ if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
399
+ return;
400
+ }
401
+
402
+ throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
403
+ }
404
+
405
+ // object property
406
+ if (Twig_Template::METHOD_CALL !== $type) {
407
+ if (isset($object->$item) || array_key_exists((string) $item, $object)) {
408
+ if ($isDefinedTest) {
409
+ return true;
410
+ }
411
+
412
+ if ($this->env->hasExtension('sandbox')) {
413
+ $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
414
+ }
415
+
416
+ return $object->$item;
417
+ }
418
+ }
419
+
420
+ $class = get_class($object);
421
+
422
+ // object method
423
+ if (!isset(self::$cache[$class]['methods'])) {
424
+ self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
425
+ }
426
+
427
+ $call = false;
428
+ $lcItem = strtolower($item);
429
+ if (isset(self::$cache[$class]['methods'][$lcItem])) {
430
+ $method = (string) $item;
431
+ } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
432
+ $method = 'get'.$item;
433
+ } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
434
+ $method = 'is'.$item;
435
+ } elseif (isset(self::$cache[$class]['methods']['__call'])) {
436
+ $method = (string) $item;
437
+ $call = true;
438
+ } else {
439
+ if ($isDefinedTest) {
440
+ return false;
441
+ }
442
+
443
+ if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
444
+ return;
445
+ }
446
+
447
+ throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
448
+ }
449
+
450
+ if ($isDefinedTest) {
451
+ return true;
452
+ }
453
+
454
+ if ($this->env->hasExtension('sandbox')) {
455
+ $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
456
+ }
457
+
458
+ // Some objects throw exceptions when they have __call, and the method we try
459
+ // to call is not supported. If ignoreStrictCheck is true, we should return null.
460
+ try {
461
+ $ret = call_user_func_array(array($object, $method), $arguments);
462
+ } catch (BadMethodCallException $e) {
463
+ if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
464
+ return;
465
+ }
466
+ throw $e;
467
+ }
468
+
469
+ // useful when calling a template method from a template
470
+ // this is not supported but unfortunately heavily used in the Symfony profiler
471
+ if ($object instanceof Twig_TemplateInterface) {
472
+ return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
473
+ }
474
+
475
+ return $ret;
476
+ }
477
+
478
+ /**
479
+ * This method is only useful when testing Twig. Do not use it.
480
+ */
481
+ public static function clearCache()
482
+ {
483
+ self::$cache = array();
484
+ }
485
+ }
classes/Twig/TemplateInterface.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface implemented by all compiled templates.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ *
17
+ * @deprecated since 1.12 (to be removed in 3.0)
18
+ */
19
+ interface Twig_TemplateInterface
20
+ {
21
+ const ANY_CALL = 'any';
22
+ const ARRAY_CALL = 'array';
23
+ const METHOD_CALL = 'method';
24
+
25
+ /**
26
+ * Renders the template with the given context and returns it as string.
27
+ *
28
+ * @param array $context An array of parameters to pass to the template
29
+ *
30
+ * @return string The rendered template
31
+ */
32
+ public function render(array $context);
33
+
34
+ /**
35
+ * Displays the template with the given context.
36
+ *
37
+ * @param array $context An array of parameters to pass to the template
38
+ * @param array $blocks An array of blocks to pass to the template
39
+ */
40
+ public function display(array $context, array $blocks = array());
41
+
42
+ /**
43
+ * Returns the bound environment for this template.
44
+ *
45
+ * @return Twig_Environment The current environment
46
+ */
47
+ public function getEnvironment();
48
+ }
classes/Twig/Test.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template test.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ * @deprecated since 1.12 (to be removed in 2.0)
17
+ */
18
+ abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
19
+ {
20
+ protected $options;
21
+ protected $arguments = array();
22
+
23
+ public function __construct(array $options = array())
24
+ {
25
+ $this->options = array_merge(array(
26
+ 'callable' => null,
27
+ ), $options);
28
+ }
29
+
30
+ public function getCallable()
31
+ {
32
+ return $this->options['callable'];
33
+ }
34
+ }
classes/Twig/TestCallableInterface.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a callable template test.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ * @deprecated since 1.12 (to be removed in 2.0)
17
+ */
18
+ interface Twig_TestCallableInterface
19
+ {
20
+ public function getCallable();
21
+ }
classes/Twig/TestInterface.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Represents a template test.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ * @deprecated since 1.12 (to be removed in 2.0)
17
+ */
18
+ interface Twig_TestInterface
19
+ {
20
+ /**
21
+ * Compiles a test.
22
+ *
23
+ * @return string The PHP code for the test
24
+ */
25
+ public function compile();
26
+ }
classes/Twig/Token.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a Token.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_Token
19
+ {
20
+ protected $value;
21
+ protected $type;
22
+ protected $lineno;
23
+
24
+ const EOF_TYPE = -1;
25
+ const TEXT_TYPE = 0;
26
+ const BLOCK_START_TYPE = 1;
27
+ const VAR_START_TYPE = 2;
28
+ const BLOCK_END_TYPE = 3;
29
+ const VAR_END_TYPE = 4;
30
+ const NAME_TYPE = 5;
31
+ const NUMBER_TYPE = 6;
32
+ const STRING_TYPE = 7;
33
+ const OPERATOR_TYPE = 8;
34
+ const PUNCTUATION_TYPE = 9;
35
+ const INTERPOLATION_START_TYPE = 10;
36
+ const INTERPOLATION_END_TYPE = 11;
37
+
38
+ /**
39
+ * Constructor.
40
+ *
41
+ * @param int $type The type of the token
42
+ * @param string $value The token value
43
+ * @param int $lineno The line position in the source
44
+ */
45
+ public function __construct($type, $value, $lineno)
46
+ {
47
+ $this->type = $type;
48
+ $this->value = $value;
49
+ $this->lineno = $lineno;
50
+ }
51
+
52
+ /**
53
+ * Returns a string representation of the token.
54
+ *
55
+ * @return string A string representation of the token
56
+ */
57
+ public function __toString()
58
+ {
59
+ return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value);
60
+ }
61
+
62
+ /**
63
+ * Tests the current token for a type and/or a value.
64
+ *
65
+ * Parameters may be:
66
+ * * just type
67
+ * * type and value (or array of possible values)
68
+ * * just value (or array of possible values) (NAME_TYPE is used as type)
69
+ *
70
+ * @param array|int $type The type to test
71
+ * @param array|string|null $values The token value
72
+ *
73
+ * @return bool
74
+ */
75
+ public function test($type, $values = null)
76
+ {
77
+ if (null === $values && !is_int($type)) {
78
+ $values = $type;
79
+ $type = self::NAME_TYPE;
80
+ }
81
+
82
+ return ($this->type === $type) && (
83
+ null === $values ||
84
+ (is_array($values) && in_array($this->value, $values)) ||
85
+ $this->value == $values
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Gets the line.
91
+ *
92
+ * @return int The source line
93
+ */
94
+ public function getLine()
95
+ {
96
+ return $this->lineno;
97
+ }
98
+
99
+ /**
100
+ * Gets the token type.
101
+ *
102
+ * @return int The token type
103
+ */
104
+ public function getType()
105
+ {
106
+ return $this->type;
107
+ }
108
+
109
+ /**
110
+ * Gets the token value.
111
+ *
112
+ * @return string The token value
113
+ */
114
+ public function getValue()
115
+ {
116
+ return $this->value;
117
+ }
118
+
119
+ /**
120
+ * Returns the constant representation (internal) of a given type.
121
+ *
122
+ * @param int $type The type as an integer
123
+ * @param bool $short Whether to return a short representation or not
124
+ *
125
+ * @return string The string representation
126
+ */
127
+ public static function typeToString($type, $short = false)
128
+ {
129
+ switch ($type) {
130
+ case self::EOF_TYPE:
131
+ $name = 'EOF_TYPE';
132
+ break;
133
+ case self::TEXT_TYPE:
134
+ $name = 'TEXT_TYPE';
135
+ break;
136
+ case self::BLOCK_START_TYPE:
137
+ $name = 'BLOCK_START_TYPE';
138
+ break;
139
+ case self::VAR_START_TYPE:
140
+ $name = 'VAR_START_TYPE';
141
+ break;
142
+ case self::BLOCK_END_TYPE:
143
+ $name = 'BLOCK_END_TYPE';
144
+ break;
145
+ case self::VAR_END_TYPE:
146
+ $name = 'VAR_END_TYPE';
147
+ break;
148
+ case self::NAME_TYPE:
149
+ $name = 'NAME_TYPE';
150
+ break;
151
+ case self::NUMBER_TYPE:
152
+ $name = 'NUMBER_TYPE';
153
+ break;
154
+ case self::STRING_TYPE:
155
+ $name = 'STRING_TYPE';
156
+ break;
157
+ case self::OPERATOR_TYPE:
158
+ $name = 'OPERATOR_TYPE';
159
+ break;
160
+ case self::PUNCTUATION_TYPE:
161
+ $name = 'PUNCTUATION_TYPE';
162
+ break;
163
+ case self::INTERPOLATION_START_TYPE:
164
+ $name = 'INTERPOLATION_START_TYPE';
165
+ break;
166
+ case self::INTERPOLATION_END_TYPE:
167
+ $name = 'INTERPOLATION_END_TYPE';
168
+ break;
169
+ default:
170
+ throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
171
+ }
172
+
173
+ return $short ? $name : 'Twig_Token::'.$name;
174
+ }
175
+
176
+ /**
177
+ * Returns the english representation of a given type.
178
+ *
179
+ * @param int $type The type as an integer
180
+ *
181
+ * @return string The string representation
182
+ */
183
+ public static function typeToEnglish($type)
184
+ {
185
+ switch ($type) {
186
+ case self::EOF_TYPE:
187
+ return 'end of template';
188
+ case self::TEXT_TYPE:
189
+ return 'text';
190
+ case self::BLOCK_START_TYPE:
191
+ return 'begin of statement block';
192
+ case self::VAR_START_TYPE:
193
+ return 'begin of print statement';
194
+ case self::BLOCK_END_TYPE:
195
+ return 'end of statement block';
196
+ case self::VAR_END_TYPE:
197
+ return 'end of print statement';
198
+ case self::NAME_TYPE:
199
+ return 'name';
200
+ case self::NUMBER_TYPE:
201
+ return 'number';
202
+ case self::STRING_TYPE:
203
+ return 'string';
204
+ case self::OPERATOR_TYPE:
205
+ return 'operator';
206
+ case self::PUNCTUATION_TYPE:
207
+ return 'punctuation';
208
+ case self::INTERPOLATION_START_TYPE:
209
+ return 'begin of string interpolation';
210
+ case self::INTERPOLATION_END_TYPE:
211
+ return 'end of string interpolation';
212
+ default:
213
+ throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
214
+ }
215
+ }
216
+ }
classes/Twig/TokenParser.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Base class for all token parsers.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ abstract class Twig_TokenParser implements Twig_TokenParserInterface
18
+ {
19
+ /**
20
+ * @var Twig_Parser
21
+ */
22
+ protected $parser;
23
+
24
+ /**
25
+ * Sets the parser associated with this token parser
26
+ *
27
+ * @param $parser A Twig_Parser instance
28
+ */
29
+ public function setParser(Twig_Parser $parser)
30
+ {
31
+ $this->parser = $parser;
32
+ }
33
+ }
classes/Twig/TokenParser/AutoEscape.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Marks a section of a template to be escaped or not.
14
+ *
15
+ * <pre>
16
+ * {% autoescape true %}
17
+ * Everything will be automatically escaped in this block
18
+ * {% endautoescape %}
19
+ *
20
+ * {% autoescape false %}
21
+ * Everything will be outputed as is in this block
22
+ * {% endautoescape %}
23
+ *
24
+ * {% autoescape true js %}
25
+ * Everything will be automatically escaped in this block
26
+ * using the js escaping strategy
27
+ * {% endautoescape %}
28
+ * </pre>
29
+ */
30
+ class Twig_TokenParser_AutoEscape extends Twig_TokenParser
31
+ {
32
+ /**
33
+ * Parses a token and returns a node.
34
+ *
35
+ * @param Twig_Token $token A Twig_Token instance
36
+ *
37
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
38
+ */
39
+ public function parse(Twig_Token $token)
40
+ {
41
+ $lineno = $token->getLine();
42
+ $stream = $this->parser->getStream();
43
+
44
+ if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
45
+ $value = 'html';
46
+ } else {
47
+ $expr = $this->parser->getExpressionParser()->parseExpression();
48
+ if (!$expr instanceof Twig_Node_Expression_Constant) {
49
+ throw new Twig_Error_Syntax('An escaping strategy must be a string or a Boolean.', $stream->getCurrent()->getLine(), $stream->getFilename());
50
+ }
51
+ $value = $expr->getAttribute('value');
52
+
53
+ $compat = true === $value || false === $value;
54
+
55
+ if (true === $value) {
56
+ $value = 'html';
57
+ }
58
+
59
+ if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
60
+ if (false === $value) {
61
+ throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename());
62
+ }
63
+
64
+ $value = $stream->next()->getValue();
65
+ }
66
+ }
67
+
68
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
69
+ $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
70
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
71
+
72
+ return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag());
73
+ }
74
+
75
+ public function decideBlockEnd(Twig_Token $token)
76
+ {
77
+ return $token->test('endautoescape');
78
+ }
79
+
80
+ /**
81
+ * Gets the tag name associated with this token parser.
82
+ *
83
+ * @return string The tag name
84
+ */
85
+ public function getTag()
86
+ {
87
+ return 'autoescape';
88
+ }
89
+ }
classes/Twig/TokenParser/Block.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Marks a section of a template as being reusable.
15
+ *
16
+ * <pre>
17
+ * {% block head %}
18
+ * <link rel="stylesheet" href="style.css" />
19
+ * <title>{% block title %}{% endblock %} - My Webpage</title>
20
+ * {% endblock %}
21
+ * </pre>
22
+ */
23
+ class Twig_TokenParser_Block extends Twig_TokenParser
24
+ {
25
+ /**
26
+ * Parses a token and returns a node.
27
+ *
28
+ * @param Twig_Token $token A Twig_Token instance
29
+ *
30
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
31
+ */
32
+ public function parse(Twig_Token $token)
33
+ {
34
+ $lineno = $token->getLine();
35
+ $stream = $this->parser->getStream();
36
+ $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
37
+ if ($this->parser->hasBlock($name)) {
38
+ throw new Twig_Error_Syntax(sprintf("The block '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $stream->getCurrent()->getLine(), $stream->getFilename());
39
+ }
40
+ $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno));
41
+ $this->parser->pushLocalScope();
42
+ $this->parser->pushBlockStack($name);
43
+
44
+ if ($stream->nextIf(Twig_Token::BLOCK_END_TYPE)) {
45
+ $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
46
+ if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) {
47
+ $value = $token->getValue();
48
+
49
+ if ($value != $name) {
50
+ throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
51
+ }
52
+ }
53
+ } else {
54
+ $body = new Twig_Node(array(
55
+ new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno),
56
+ ));
57
+ }
58
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
59
+
60
+ $block->setNode('body', $body);
61
+ $this->parser->popBlockStack();
62
+ $this->parser->popLocalScope();
63
+
64
+ return new Twig_Node_BlockReference($name, $lineno, $this->getTag());
65
+ }
66
+
67
+ public function decideBlockEnd(Twig_Token $token)
68
+ {
69
+ return $token->test('endblock');
70
+ }
71
+
72
+ /**
73
+ * Gets the tag name associated with this token parser.
74
+ *
75
+ * @return string The tag name
76
+ */
77
+ public function getTag()
78
+ {
79
+ return 'block';
80
+ }
81
+ }
classes/Twig/TokenParser/Do.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Evaluates an expression, discarding the returned value.
14
+ */
15
+ class Twig_TokenParser_Do extends Twig_TokenParser
16
+ {
17
+ /**
18
+ * Parses a token and returns a node.
19
+ *
20
+ * @param Twig_Token $token A Twig_Token instance
21
+ *
22
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
23
+ */
24
+ public function parse(Twig_Token $token)
25
+ {
26
+ $expr = $this->parser->getExpressionParser()->parseExpression();
27
+
28
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
29
+
30
+ return new Twig_Node_Do($expr, $token->getLine(), $this->getTag());
31
+ }
32
+
33
+ /**
34
+ * Gets the tag name associated with this token parser.
35
+ *
36
+ * @return string The tag name
37
+ */
38
+ public function getTag()
39
+ {
40
+ return 'do';
41
+ }
42
+ }
classes/Twig/TokenParser/Embed.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2012 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Embeds a template.
14
+ */
15
+ class Twig_TokenParser_Embed extends Twig_TokenParser_Include
16
+ {
17
+ /**
18
+ * Parses a token and returns a node.
19
+ *
20
+ * @param Twig_Token $token A Twig_Token instance
21
+ *
22
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
23
+ */
24
+ public function parse(Twig_Token $token)
25
+ {
26
+ $stream = $this->parser->getStream();
27
+
28
+ $parent = $this->parser->getExpressionParser()->parseExpression();
29
+
30
+ list($variables, $only, $ignoreMissing) = $this->parseArguments();
31
+
32
+ // inject a fake parent to make the parent() function work
33
+ $stream->injectTokens(array(
34
+ new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()),
35
+ new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()),
36
+ new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()),
37
+ new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()),
38
+ ));
39
+
40
+ $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true);
41
+
42
+ // override the parent with the correct one
43
+ $module->setNode('parent', $parent);
44
+
45
+ $this->parser->embedTemplate($module);
46
+
47
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
48
+
49
+ return new Twig_Node_Embed($module->getAttribute('filename'), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
50
+ }
51
+
52
+ public function decideBlockEnd(Twig_Token $token)
53
+ {
54
+ return $token->test('endembed');
55
+ }
56
+
57
+ /**
58
+ * Gets the tag name associated with this token parser.
59
+ *
60
+ * @return string The tag name
61
+ */
62
+ public function getTag()
63
+ {
64
+ return 'embed';
65
+ }
66
+ }
classes/Twig/TokenParser/Extends.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Extends a template by another one.
15
+ *
16
+ * <pre>
17
+ * {% extends "base.html" %}
18
+ * </pre>
19
+ */
20
+ class Twig_TokenParser_Extends extends Twig_TokenParser
21
+ {
22
+ /**
23
+ * Parses a token and returns a node.
24
+ *
25
+ * @param Twig_Token $token A Twig_Token instance
26
+ *
27
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
28
+ */
29
+ public function parse(Twig_Token $token)
30
+ {
31
+ if (!$this->parser->isMainScope()) {
32
+ throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine(), $this->parser->getFilename());
33
+ }
34
+
35
+ if (null !== $this->parser->getParent()) {
36
+ throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine(), $this->parser->getFilename());
37
+ }
38
+ $this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
39
+
40
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
41
+ }
42
+
43
+ /**
44
+ * Gets the tag name associated with this token parser.
45
+ *
46
+ * @return string The tag name
47
+ */
48
+ public function getTag()
49
+ {
50
+ return 'extends';
51
+ }
52
+ }
classes/Twig/TokenParser/Filter.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Filters a section of a template by applying filters.
14
+ *
15
+ * <pre>
16
+ * {% filter upper %}
17
+ * This text becomes uppercase
18
+ * {% endfilter %}
19
+ * </pre>
20
+ */
21
+ class Twig_TokenParser_Filter extends Twig_TokenParser
22
+ {
23
+ /**
24
+ * Parses a token and returns a node.
25
+ *
26
+ * @param Twig_Token $token A Twig_Token instance
27
+ *
28
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
29
+ */
30
+ public function parse(Twig_Token $token)
31
+ {
32
+ $name = $this->parser->getVarName();
33
+ $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), true, $token->getLine(), $this->getTag());
34
+
35
+ $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
36
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
37
+
38
+ $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
39
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
40
+
41
+ $block = new Twig_Node_Block($name, $body, $token->getLine());
42
+ $this->parser->setBlock($name, $block);
43
+
44
+ return new Twig_Node_Print($filter, $token->getLine(), $this->getTag());
45
+ }
46
+
47
+ public function decideBlockEnd(Twig_Token $token)
48
+ {
49
+ return $token->test('endfilter');
50
+ }
51
+
52
+ /**
53
+ * Gets the tag name associated with this token parser.
54
+ *
55
+ * @return string The tag name
56
+ */
57
+ public function getTag()
58
+ {
59
+ return 'filter';
60
+ }
61
+ }
classes/Twig/TokenParser/Flush.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Flushes the output to the client.
14
+ *
15
+ * @see flush()
16
+ */
17
+ class Twig_TokenParser_Flush extends Twig_TokenParser
18
+ {
19
+ /**
20
+ * Parses a token and returns a node.
21
+ *
22
+ * @param Twig_Token $token A Twig_Token instance
23
+ *
24
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
25
+ */
26
+ public function parse(Twig_Token $token)
27
+ {
28
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
29
+
30
+ return new Twig_Node_Flush($token->getLine(), $this->getTag());
31
+ }
32
+
33
+ /**
34
+ * Gets the tag name associated with this token parser.
35
+ *
36
+ * @return string The tag name
37
+ */
38
+ public function getTag()
39
+ {
40
+ return 'flush';
41
+ }
42
+ }
classes/Twig/TokenParser/For.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Loops over each item of a sequence.
15
+ *
16
+ * <pre>
17
+ * <ul>
18
+ * {% for user in users %}
19
+ * <li>{{ user.username|e }}</li>
20
+ * {% endfor %}
21
+ * </ul>
22
+ * </pre>
23
+ */
24
+ class Twig_TokenParser_For extends Twig_TokenParser
25
+ {
26
+ /**
27
+ * Parses a token and returns a node.
28
+ *
29
+ * @param Twig_Token $token A Twig_Token instance
30
+ *
31
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
32
+ */
33
+ public function parse(Twig_Token $token)
34
+ {
35
+ $lineno = $token->getLine();
36
+ $stream = $this->parser->getStream();
37
+ $targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
38
+ $stream->expect(Twig_Token::OPERATOR_TYPE, 'in');
39
+ $seq = $this->parser->getExpressionParser()->parseExpression();
40
+
41
+ $ifexpr = null;
42
+ if ($stream->nextIf(Twig_Token::NAME_TYPE, 'if')) {
43
+ $ifexpr = $this->parser->getExpressionParser()->parseExpression();
44
+ }
45
+
46
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
47
+ $body = $this->parser->subparse(array($this, 'decideForFork'));
48
+ if ($stream->next()->getValue() == 'else') {
49
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
50
+ $else = $this->parser->subparse(array($this, 'decideForEnd'), true);
51
+ } else {
52
+ $else = null;
53
+ }
54
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
55
+
56
+ if (count($targets) > 1) {
57
+ $keyTarget = $targets->getNode(0);
58
+ $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getLine());
59
+ $valueTarget = $targets->getNode(1);
60
+ $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
61
+ } else {
62
+ $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
63
+ $valueTarget = $targets->getNode(0);
64
+ $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
65
+ }
66
+
67
+ if ($ifexpr) {
68
+ $this->checkLoopUsageCondition($stream, $ifexpr);
69
+ $this->checkLoopUsageBody($stream, $body);
70
+ }
71
+
72
+ return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
73
+ }
74
+
75
+ public function decideForFork(Twig_Token $token)
76
+ {
77
+ return $token->test(array('else', 'endfor'));
78
+ }
79
+
80
+ public function decideForEnd(Twig_Token $token)
81
+ {
82
+ return $token->test('endfor');
83
+ }
84
+
85
+ // the loop variable cannot be used in the condition
86
+ protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
87
+ {
88
+ if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
89
+ throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition', $node->getLine(), $stream->getFilename());
90
+ }
91
+
92
+ foreach ($node as $n) {
93
+ if (!$n) {
94
+ continue;
95
+ }
96
+
97
+ $this->checkLoopUsageCondition($stream, $n);
98
+ }
99
+ }
100
+
101
+ // check usage of non-defined loop-items
102
+ // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
103
+ protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node)
104
+ {
105
+ if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
106
+ $attribute = $node->getNode('attribute');
107
+ if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
108
+ throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition', $attribute->getAttribute('value')), $node->getLine(), $stream->getFilename());
109
+ }
110
+ }
111
+
112
+ // should check for parent.loop.XXX usage
113
+ if ($node instanceof Twig_Node_For) {
114
+ return;
115
+ }
116
+
117
+ foreach ($node as $n) {
118
+ if (!$n) {
119
+ continue;
120
+ }
121
+
122
+ $this->checkLoopUsageBody($stream, $n);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Gets the tag name associated with this token parser.
128
+ *
129
+ * @return string The tag name
130
+ */
131
+ public function getTag()
132
+ {
133
+ return 'for';
134
+ }
135
+ }
classes/Twig/TokenParser/From.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Imports macros.
14
+ *
15
+ * <pre>
16
+ * {% from 'forms.html' import forms %}
17
+ * </pre>
18
+ */
19
+ class Twig_TokenParser_From extends Twig_TokenParser
20
+ {
21
+ /**
22
+ * Parses a token and returns a node.
23
+ *
24
+ * @param Twig_Token $token A Twig_Token instance
25
+ *
26
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
27
+ */
28
+ public function parse(Twig_Token $token)
29
+ {
30
+ $macro = $this->parser->getExpressionParser()->parseExpression();
31
+ $stream = $this->parser->getStream();
32
+ $stream->expect('import');
33
+
34
+ $targets = array();
35
+ do {
36
+ $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
37
+
38
+ $alias = $name;
39
+ if ($stream->nextIf('as')) {
40
+ $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
41
+ }
42
+
43
+ $targets[$name] = $alias;
44
+
45
+ if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
46
+ break;
47
+ }
48
+ } while (true);
49
+
50
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
51
+
52
+ $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
53
+
54
+ foreach ($targets as $name => $alias) {
55
+ $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
56
+ }
57
+
58
+ return $node;
59
+ }
60
+
61
+ /**
62
+ * Gets the tag name associated with this token parser.
63
+ *
64
+ * @return string The tag name
65
+ */
66
+ public function getTag()
67
+ {
68
+ return 'from';
69
+ }
70
+ }
classes/Twig/TokenParser/If.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Tests a condition.
15
+ *
16
+ * <pre>
17
+ * {% if users %}
18
+ * <ul>
19
+ * {% for user in users %}
20
+ * <li>{{ user.username|e }}</li>
21
+ * {% endfor %}
22
+ * </ul>
23
+ * {% endif %}
24
+ * </pre>
25
+ */
26
+ class Twig_TokenParser_If extends Twig_TokenParser
27
+ {
28
+ /**
29
+ * Parses a token and returns a node.
30
+ *
31
+ * @param Twig_Token $token A Twig_Token instance
32
+ *
33
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
34
+ */
35
+ public function parse(Twig_Token $token)
36
+ {
37
+ $lineno = $token->getLine();
38
+ $expr = $this->parser->getExpressionParser()->parseExpression();
39
+ $stream = $this->parser->getStream();
40
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
41
+ $body = $this->parser->subparse(array($this, 'decideIfFork'));
42
+ $tests = array($expr, $body);
43
+ $else = null;
44
+
45
+ $end = false;
46
+ while (!$end) {
47
+ switch ($stream->next()->getValue()) {
48
+ case 'else':
49
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
50
+ $else = $this->parser->subparse(array($this, 'decideIfEnd'));
51
+ break;
52
+
53
+ case 'elseif':
54
+ $expr = $this->parser->getExpressionParser()->parseExpression();
55
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
56
+ $body = $this->parser->subparse(array($this, 'decideIfFork'));
57
+ $tests[] = $expr;
58
+ $tests[] = $body;
59
+ break;
60
+
61
+ case 'endif':
62
+ $end = true;
63
+ break;
64
+
65
+ default:
66
+ throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), $stream->getCurrent()->getLine(), $stream->getFilename());
67
+ }
68
+ }
69
+
70
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
71
+
72
+ return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag());
73
+ }
74
+
75
+ public function decideIfFork(Twig_Token $token)
76
+ {
77
+ return $token->test(array('elseif', 'else', 'endif'));
78
+ }
79
+
80
+ public function decideIfEnd(Twig_Token $token)
81
+ {
82
+ return $token->test(array('endif'));
83
+ }
84
+
85
+ /**
86
+ * Gets the tag name associated with this token parser.
87
+ *
88
+ * @return string The tag name
89
+ */
90
+ public function getTag()
91
+ {
92
+ return 'if';
93
+ }
94
+ }
classes/Twig/TokenParser/Import.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Imports macros.
14
+ *
15
+ * <pre>
16
+ * {% import 'forms.html' as forms %}
17
+ * </pre>
18
+ */
19
+ class Twig_TokenParser_Import extends Twig_TokenParser
20
+ {
21
+ /**
22
+ * Parses a token and returns a node.
23
+ *
24
+ * @param Twig_Token $token A Twig_Token instance
25
+ *
26
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
27
+ */
28
+ public function parse(Twig_Token $token)
29
+ {
30
+ $macro = $this->parser->getExpressionParser()->parseExpression();
31
+ $this->parser->getStream()->expect('as');
32
+ $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine());
33
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
34
+
35
+ $this->parser->addImportedSymbol('template', $var->getAttribute('name'));
36
+
37
+ return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag());
38
+ }
39
+
40
+ /**
41
+ * Gets the tag name associated with this token parser.
42
+ *
43
+ * @return string The tag name
44
+ */
45
+ public function getTag()
46
+ {
47
+ return 'import';
48
+ }
49
+ }
classes/Twig/TokenParser/Include.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Includes a template.
15
+ *
16
+ * <pre>
17
+ * {% include 'header.html' %}
18
+ * Body
19
+ * {% include 'footer.html' %}
20
+ * </pre>
21
+ */
22
+ class Twig_TokenParser_Include extends Twig_TokenParser
23
+ {
24
+ /**
25
+ * Parses a token and returns a node.
26
+ *
27
+ * @param Twig_Token $token A Twig_Token instance
28
+ *
29
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
30
+ */
31
+ public function parse(Twig_Token $token)
32
+ {
33
+ $expr = $this->parser->getExpressionParser()->parseExpression();
34
+
35
+ list($variables, $only, $ignoreMissing) = $this->parseArguments();
36
+
37
+ return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
38
+ }
39
+
40
+ protected function parseArguments()
41
+ {
42
+ $stream = $this->parser->getStream();
43
+
44
+ $ignoreMissing = false;
45
+ if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) {
46
+ $stream->expect(Twig_Token::NAME_TYPE, 'missing');
47
+
48
+ $ignoreMissing = true;
49
+ }
50
+
51
+ $variables = null;
52
+ if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) {
53
+ $variables = $this->parser->getExpressionParser()->parseExpression();
54
+ }
55
+
56
+ $only = false;
57
+ if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) {
58
+ $only = true;
59
+ }
60
+
61
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
62
+
63
+ return array($variables, $only, $ignoreMissing);
64
+ }
65
+
66
+ /**
67
+ * Gets the tag name associated with this token parser.
68
+ *
69
+ * @return string The tag name
70
+ */
71
+ public function getTag()
72
+ {
73
+ return 'include';
74
+ }
75
+ }
classes/Twig/TokenParser/Macro.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Defines a macro.
14
+ *
15
+ * <pre>
16
+ * {% macro input(name, value, type, size) %}
17
+ * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
18
+ * {% endmacro %}
19
+ * </pre>
20
+ */
21
+ class Twig_TokenParser_Macro extends Twig_TokenParser
22
+ {
23
+ /**
24
+ * Parses a token and returns a node.
25
+ *
26
+ * @param Twig_Token $token A Twig_Token instance
27
+ *
28
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
29
+ */
30
+ public function parse(Twig_Token $token)
31
+ {
32
+ $lineno = $token->getLine();
33
+ $stream = $this->parser->getStream();
34
+ $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
35
+
36
+ $arguments = $this->parser->getExpressionParser()->parseArguments(true, true);
37
+
38
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
39
+ $this->parser->pushLocalScope();
40
+ $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
41
+ if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) {
42
+ $value = $token->getValue();
43
+
44
+ if ($value != $name) {
45
+ throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
46
+ }
47
+ }
48
+ $this->parser->popLocalScope();
49
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
50
+
51
+ $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag()));
52
+ }
53
+
54
+ public function decideBlockEnd(Twig_Token $token)
55
+ {
56
+ return $token->test('endmacro');
57
+ }
58
+
59
+ /**
60
+ * Gets the tag name associated with this token parser.
61
+ *
62
+ * @return string The tag name
63
+ */
64
+ public function getTag()
65
+ {
66
+ return 'macro';
67
+ }
68
+ }
classes/Twig/TokenParser/Sandbox.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode.
14
+ *
15
+ * <pre>
16
+ * {% sandbox %}
17
+ * {% include 'user.html' %}
18
+ * {% endsandbox %}
19
+ * </pre>
20
+ *
21
+ * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details
22
+ */
23
+ class Twig_TokenParser_Sandbox extends Twig_TokenParser
24
+ {
25
+ /**
26
+ * Parses a token and returns a node.
27
+ *
28
+ * @param Twig_Token $token A Twig_Token instance
29
+ *
30
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
31
+ */
32
+ public function parse(Twig_Token $token)
33
+ {
34
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
35
+ $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
36
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
37
+
38
+ // in a sandbox tag, only include tags are allowed
39
+ if (!$body instanceof Twig_Node_Include) {
40
+ foreach ($body as $node) {
41
+ if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
42
+ continue;
43
+ }
44
+
45
+ if (!$node instanceof Twig_Node_Include) {
46
+ throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section', $node->getLine(), $this->parser->getFilename());
47
+ }
48
+ }
49
+ }
50
+
51
+ return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag());
52
+ }
53
+
54
+ public function decideBlockEnd(Twig_Token $token)
55
+ {
56
+ return $token->test('endsandbox');
57
+ }
58
+
59
+ /**
60
+ * Gets the tag name associated with this token parser.
61
+ *
62
+ * @return string The tag name
63
+ */
64
+ public function getTag()
65
+ {
66
+ return 'sandbox';
67
+ }
68
+ }
classes/Twig/TokenParser/Set.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Defines a variable.
14
+ *
15
+ * <pre>
16
+ * {% set foo = 'foo' %}
17
+ *
18
+ * {% set foo = [1, 2] %}
19
+ *
20
+ * {% set foo = {'foo': 'bar'} %}
21
+ *
22
+ * {% set foo = 'foo' ~ 'bar' %}
23
+ *
24
+ * {% set foo, bar = 'foo', 'bar' %}
25
+ *
26
+ * {% set foo %}Some content{% endset %}
27
+ * </pre>
28
+ */
29
+ class Twig_TokenParser_Set extends Twig_TokenParser
30
+ {
31
+ /**
32
+ * Parses a token and returns a node.
33
+ *
34
+ * @param Twig_Token $token A Twig_Token instance
35
+ *
36
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
37
+ */
38
+ public function parse(Twig_Token $token)
39
+ {
40
+ $lineno = $token->getLine();
41
+ $stream = $this->parser->getStream();
42
+ $names = $this->parser->getExpressionParser()->parseAssignmentExpression();
43
+
44
+ $capture = false;
45
+ if ($stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
46
+ $values = $this->parser->getExpressionParser()->parseMultitargetExpression();
47
+
48
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
49
+
50
+ if (count($names) !== count($values)) {
51
+ throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignments.", $stream->getCurrent()->getLine(), $stream->getFilename());
52
+ }
53
+ } else {
54
+ $capture = true;
55
+
56
+ if (count($names) > 1) {
57
+ throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $stream->getCurrent()->getLine(), $stream->getFilename());
58
+ }
59
+
60
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
61
+
62
+ $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
63
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
64
+ }
65
+
66
+ return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag());
67
+ }
68
+
69
+ public function decideBlockEnd(Twig_Token $token)
70
+ {
71
+ return $token->test('endset');
72
+ }
73
+
74
+ /**
75
+ * Gets the tag name associated with this token parser.
76
+ *
77
+ * @return string The tag name
78
+ */
79
+ public function getTag()
80
+ {
81
+ return 'set';
82
+ }
83
+ }
classes/Twig/TokenParser/Spaceless.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Remove whitespaces between HTML tags.
14
+ *
15
+ * <pre>
16
+ * {% spaceless %}
17
+ * <div>
18
+ * <strong>foo</strong>
19
+ * </div>
20
+ * {% endspaceless %}
21
+ *
22
+ * {# output will be <div><strong>foo</strong></div> #}
23
+ * </pre>
24
+ */
25
+ class Twig_TokenParser_Spaceless extends Twig_TokenParser
26
+ {
27
+ /**
28
+ * Parses a token and returns a node.
29
+ *
30
+ * @param Twig_Token $token A Twig_Token instance
31
+ *
32
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
33
+ */
34
+ public function parse(Twig_Token $token)
35
+ {
36
+ $lineno = $token->getLine();
37
+
38
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
39
+ $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true);
40
+ $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
41
+
42
+ return new Twig_Node_Spaceless($body, $lineno, $this->getTag());
43
+ }
44
+
45
+ public function decideSpacelessEnd(Twig_Token $token)
46
+ {
47
+ return $token->test('endspaceless');
48
+ }
49
+
50
+ /**
51
+ * Gets the tag name associated with this token parser.
52
+ *
53
+ * @return string The tag name
54
+ */
55
+ public function getTag()
56
+ {
57
+ return 'spaceless';
58
+ }
59
+ }
classes/Twig/TokenParser/Use.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2011 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Imports blocks defined in another template into the current template.
14
+ *
15
+ * <pre>
16
+ * {% extends "base.html" %}
17
+ *
18
+ * {% use "blocks.html" %}
19
+ *
20
+ * {% block title %}{% endblock %}
21
+ * {% block content %}{% endblock %}
22
+ * </pre>
23
+ *
24
+ * @see http://www.twig-project.org/doc/templates.html#horizontal-reuse for details.
25
+ */
26
+ class Twig_TokenParser_Use extends Twig_TokenParser
27
+ {
28
+ /**
29
+ * Parses a token and returns a node.
30
+ *
31
+ * @param Twig_Token $token A Twig_Token instance
32
+ *
33
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
34
+ */
35
+ public function parse(Twig_Token $token)
36
+ {
37
+ $template = $this->parser->getExpressionParser()->parseExpression();
38
+ $stream = $this->parser->getStream();
39
+
40
+ if (!$template instanceof Twig_Node_Expression_Constant) {
41
+ throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getFilename());
42
+ }
43
+
44
+ $targets = array();
45
+ if ($stream->nextIf('with')) {
46
+ do {
47
+ $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
48
+
49
+ $alias = $name;
50
+ if ($stream->nextIf('as')) {
51
+ $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
52
+ }
53
+
54
+ $targets[$name] = new Twig_Node_Expression_Constant($alias, -1);
55
+
56
+ if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
57
+ break;
58
+ }
59
+ } while (true);
60
+ }
61
+
62
+ $stream->expect(Twig_Token::BLOCK_END_TYPE);
63
+
64
+ $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
65
+ }
66
+
67
+ /**
68
+ * Gets the tag name associated with this token parser.
69
+ *
70
+ * @return string The tag name
71
+ */
72
+ public function getTag()
73
+ {
74
+ return 'use';
75
+ }
76
+ }
classes/Twig/TokenParserBroker.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ * (c) 2010 Arnaud Le Blanc
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Default implementation of a token parser broker.
15
+ *
16
+ * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
17
+ * @deprecated since 1.12 (to be removed in 2.0)
18
+ */
19
+ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
20
+ {
21
+ protected $parser;
22
+ protected $parsers = array();
23
+ protected $brokers = array();
24
+
25
+ /**
26
+ * Constructor.
27
+ *
28
+ * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances
29
+ * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances
30
+ */
31
+ public function __construct($parsers = array(), $brokers = array())
32
+ {
33
+ foreach ($parsers as $parser) {
34
+ if (!$parser instanceof Twig_TokenParserInterface) {
35
+ throw new LogicException('$parsers must a an array of Twig_TokenParserInterface');
36
+ }
37
+ $this->parsers[$parser->getTag()] = $parser;
38
+ }
39
+ foreach ($brokers as $broker) {
40
+ if (!$broker instanceof Twig_TokenParserBrokerInterface) {
41
+ throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface');
42
+ }
43
+ $this->brokers[] = $broker;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Adds a TokenParser.
49
+ *
50
+ * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
51
+ */
52
+ public function addTokenParser(Twig_TokenParserInterface $parser)
53
+ {
54
+ $this->parsers[$parser->getTag()] = $parser;
55
+ }
56
+
57
+ /**
58
+ * Removes a TokenParser.
59
+ *
60
+ * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
61
+ */
62
+ public function removeTokenParser(Twig_TokenParserInterface $parser)
63
+ {
64
+ $name = $parser->getTag();
65
+ if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) {
66
+ unset($this->parsers[$name]);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Adds a TokenParserBroker.
72
+ *
73
+ * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
74
+ */
75
+ public function addTokenParserBroker(Twig_TokenParserBroker $broker)
76
+ {
77
+ $this->brokers[] = $broker;
78
+ }
79
+
80
+ /**
81
+ * Removes a TokenParserBroker.
82
+ *
83
+ * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
84
+ */
85
+ public function removeTokenParserBroker(Twig_TokenParserBroker $broker)
86
+ {
87
+ if (false !== $pos = array_search($broker, $this->brokers)) {
88
+ unset($this->brokers[$pos]);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Gets a suitable TokenParser for a tag.
94
+ *
95
+ * First looks in parsers, then in brokers.
96
+ *
97
+ * @param string $tag A tag name
98
+ *
99
+ * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found
100
+ */
101
+ public function getTokenParser($tag)
102
+ {
103
+ if (isset($this->parsers[$tag])) {
104
+ return $this->parsers[$tag];
105
+ }
106
+ $broker = end($this->brokers);
107
+ while (false !== $broker) {
108
+ $parser = $broker->getTokenParser($tag);
109
+ if (null !== $parser) {
110
+ return $parser;
111
+ }
112
+ $broker = prev($this->brokers);
113
+ }
114
+ }
115
+
116
+ public function getParsers()
117
+ {
118
+ return $this->parsers;
119
+ }
120
+
121
+ public function getParser()
122
+ {
123
+ return $this->parser;
124
+ }
125
+
126
+ public function setParser(Twig_ParserInterface $parser)
127
+ {
128
+ $this->parser = $parser;
129
+ foreach ($this->parsers as $tokenParser) {
130
+ $tokenParser->setParser($parser);
131
+ }
132
+ foreach ($this->brokers as $broker) {
133
+ $broker->setParser($parser);
134
+ }
135
+ }
136
+ }
classes/Twig/TokenParserBrokerInterface.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ * (c) 2010 Arnaud Le Blanc
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Interface implemented by token parser brokers.
15
+ *
16
+ * Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
17
+ *
18
+ * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
19
+ * @deprecated since 1.12 (to be removed in 2.0)
20
+ */
21
+ interface Twig_TokenParserBrokerInterface
22
+ {
23
+ /**
24
+ * Gets a TokenParser suitable for a tag.
25
+ *
26
+ * @param string $tag A tag name
27
+ *
28
+ * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found
29
+ */
30
+ public function getTokenParser($tag);
31
+
32
+ /**
33
+ * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of.
34
+ *
35
+ * @param Twig_ParserInterface $parser A Twig_ParserInterface interface
36
+ */
37
+ public function setParser(Twig_ParserInterface $parser);
38
+
39
+ /**
40
+ * Gets the Twig_ParserInterface.
41
+ *
42
+ * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null
43
+ */
44
+ public function getParser();
45
+ }
classes/Twig/TokenParserInterface.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2010 Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ /**
13
+ * Interface implemented by token parsers.
14
+ *
15
+ * @author Fabien Potencier <fabien@symfony.com>
16
+ */
17
+ interface Twig_TokenParserInterface
18
+ {
19
+ /**
20
+ * Sets the parser associated with this token parser
21
+ *
22
+ * @param $parser A Twig_Parser instance
23
+ */
24
+ public function setParser(Twig_Parser $parser);
25
+
26
+ /**
27
+ * Parses a token and returns a node.
28
+ *
29
+ * @param Twig_Token $token A Twig_Token instance
30
+ *
31
+ * @return Twig_NodeInterface A Twig_NodeInterface instance
32
+ *
33
+ * @throws Twig_Error_Syntax
34
+ */
35
+ public function parse(Twig_Token $token);
36
+
37
+ /**
38
+ * Gets the tag name associated with this token parser.
39
+ *
40
+ * @return string The tag name
41
+ */
42
+ public function getTag();
43
+ }
classes/Twig/TokenStream.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) 2009 Fabien Potencier
7
+ * (c) 2009 Armin Ronacher
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ /**
14
+ * Represents a token stream.
15
+ *
16
+ * @author Fabien Potencier <fabien@symfony.com>
17
+ */
18
+ class Twig_TokenStream
19
+ {
20
+ protected $tokens;
21
+ protected $current;
22
+ protected $filename;
23
+
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @param array $tokens An array of tokens
28
+ * @param string $filename The name of the filename which tokens are associated with
29
+ */
30
+ public function __construct(array $tokens, $filename = null)
31
+ {
32
+ $this->tokens = $tokens;
33
+ $this->current = 0;
34
+ $this->filename = $filename;
35
+ }
36
+
37
+ /**
38
+ * Returns a string representation of the token stream.
39
+ *
40
+ * @return string
41
+ */
42
+ public function __toString()
43
+ {
44
+ return implode("\n", $this->tokens);
45
+ }
46
+
47
+ public function injectTokens(array $tokens)
48
+ {
49
+ $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current));
50
+ }
51
+
52
+ /**
53
+ * Sets the pointer to the next token and returns the old one.
54
+ *
55
+ * @return Twig_Token
56
+ */
57
+ public function next()
58
+ {
59
+ if (!isset($this->tokens[++$this->current])) {
60
+ throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current - 1]->getLine(), $this->filename);
61
+ }
62
+
63
+ return $this->tokens[$this->current - 1];
64
+ }
65
+
66
+ /**
67
+ * Tests a token, sets the pointer to the next one and returns it or throws a syntax error.
68
+ *
69
+ * @return Twig_Token|null The next token if the condition is true, null otherwise
70
+ */
71
+ public function nextIf($primary, $secondary = null)
72
+ {
73
+ if ($this->tokens[$this->current]->test($primary, $secondary)) {
74
+ return $this->next();
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Tests a token and returns it or throws a syntax error.
80
+ *
81
+ * @return Twig_Token
82
+ */
83
+ public function expect($type, $value = null, $message = null)
84
+ {
85
+ $token = $this->tokens[$this->current];
86
+ if (!$token->test($type, $value)) {
87
+ $line = $token->getLine();
88
+ throw new Twig_Error_Syntax(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)',
89
+ $message ? $message.'. ' : '',
90
+ Twig_Token::typeToEnglish($token->getType()), $token->getValue(),
91
+ Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''),
92
+ $line,
93
+ $this->filename
94
+ );
95
+ }
96
+ $this->next();
97
+
98
+ return $token;
99
+ }
100
+
101
+ /**
102
+ * Looks at the next token.
103
+ *
104
+ * @param int $number
105
+ *
106
+ * @return Twig_Token
107
+ */
108
+ public function look($number = 1)
109
+ {
110
+ if (!isset($this->tokens[$this->current + $number])) {
111
+ throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current + $number - 1]->getLine(), $this->filename);
112
+ }
113
+
114
+ return $this->tokens[$this->current + $number];
115
+ }
116
+
117
+ /**
118
+ * Tests the current token
119
+ *
120
+ * @return bool
121
+ */
122
+ public function test($primary, $secondary = null)
123
+ {
124
+ return $this->tokens[$this->current]->test($primary, $secondary);
125
+ }
126
+
127
+ /**
128
+ * Checks if end of stream was reached
129
+ *
130
+ * @return bool
131
+ */
132
+ public function isEOF()
133
+ {
134
+ return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE;
135
+ }
136
+
137
+ /**
138
+ * Gets the current token
139
+ *
140
+ * @return Twig_Token
141
+ */
142
+ public function getCurrent()
143
+ {
144
+ return $this->tokens[$this->current];
145
+ }
146
+
147
+ /**
148
+ * Gets the filename associated with this stream
149
+ *
150
+ * @return string
151
+ */
152
+ public function getFilename()
153
+ {
154
+ return $this->filename;
155
+ }
156
+ }
classes/baseObject.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ abstract class baseObjectPps {
3
+ protected $_internalErrors = array();
4
+ protected $_haveErrors = false;
5
+ public function pushError($error, $key = '') {
6
+ if(is_array($error)) {
7
+ $this->_internalErrors = array_merge ($this->_internalErrors, $error);
8
+ } elseif(empty($key)) {
9
+ $this->_internalErrors[] = $error;
10
+ } else {
11
+ $this->_internalErrors[ $key ] = $error;
12
+ }
13
+ $this->_haveErrors = true;
14
+ }
15
+ public function getErrors() {
16
+ return $this->_internalErrors;
17
+ }
18
+ public function haveErrors() {
19
+ return $this->_haveErrors;
20
+ }
21
+ }
22
+
classes/controller.php ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ abstract class controllerPps {
3
+ protected $_models = array();
4
+ protected $_views = array();
5
+ protected $_task = '';
6
+ protected $_defaultView = '';
7
+ protected $_code = '';
8
+ public function __construct($code) {
9
+ $this->setCode($code);
10
+ $this->_defaultView = $this->getCode();
11
+ }
12
+ public function init() {
13
+ /*load model and other preload data goes here*/
14
+ }
15
+ protected function _onBeforeInit() {
16
+
17
+ }
18
+ protected function _onAfterInit() {
19
+
20
+ }
21
+ public function setCode($code) {
22
+ $this->_code = $code;
23
+ }
24
+ public function getCode() {
25
+ return $this->_code;
26
+ }
27
+ public function exec($task = '') {
28
+ if(method_exists($this, $task)) {
29
+ $this->_task = $task; //For multicontrollers module version - who know, maybe that's will be?))
30
+ return $this->$task();
31
+ }
32
+ return null;
33
+ }
34
+ public function getView($name = '') {
35
+ if(empty($name)) $name = $this->getCode();
36
+ if(!isset($this->_views[$name])) {
37
+ $this->_views[$name] = $this->_createView($name);
38
+ }
39
+ return $this->_views[$name];
40
+ }
41
+ public function getModel($name = '') {
42
+ if(!$name)
43
+ $name = $this->_code;
44
+ if(!isset($this->_models[$name])) {
45
+ $this->_models[$name] = $this->_createModel($name);
46
+ }
47
+ return $this->_models[$name];
48
+ }
49
+ protected function _createModel($name = '') {
50
+ if(empty($name)) $name = $this->getCode();
51
+ $parentModule = framePps::_()->getModule( $this->getCode() );
52
+ $className = '';
53
+ if(importPps($parentModule->getModDir(). 'models'. DS. $name. '.php')) {
54
+ $className = toeGetClassNamePps($name. 'Model');
55
+ }
56
+
57
+ if($className) {
58
+ $model = new $className();
59
+ $model->setCode( $this->getCode() );
60
+ return $model;
61
+ }
62
+ return NULL;
63
+ }
64
+ protected function _createView($name = '') {
65
+ if(empty($name)) $name = $this->getCode();
66
+ $parentModule = framePps::_()->getModule( $this->getCode() );
67
+ $className = '';
68
+
69
+ if(importPps($parentModule->getModDir(). 'views'. DS. $name. '.php')) {
70
+ $className = toeGetClassNamePps($name. 'View');
71
+ }
72
+
73
+ if($className) {
74
+ $view = new $className();
75
+ $view->setCode( $this->getCode() );
76
+ return $view;
77
+ }
78
+ return NULL;
79
+ }
80
+ public function display($viewName = '') {
81
+ $view = NULL;
82
+ if(($view = $this->getView($viewName)) === NULL) {
83
+ $view = $this->getView(); //Get default view
84
+ }
85
+ if($view) {
86
+ $view->display();
87
+ }
88
+ }
89
+ public function __call($name, $arguments) {
90
+ $model = $this->getModel();
91
+ if(method_exists($model, $name))
92
+ return $model->$name($arguments[0]);
93
+ else
94
+ return false;
95
+ }
96
+ /**
97
+ * Retrive permissions for controller methods if exist.
98
+ * If need - should be redefined in each controller where it required.
99
+ * @return array with permissions
100
+ * @example :
101
+ return array(
102
+ S_METHODS => array(
103
+ 'save' => array(PPS_ADMIN),
104
+ 'remove' => array(PPS_ADMIN),
105
+ 'restore' => PPS_ADMIN,
106
+ ),
107
+ S_USERLEVELS => array(
108
+ S_ADMIN => array('save', 'remove', 'restore')
109
+ ),
110
+ );
111
+ * Can be used on of sub-array - PPS_METHODS or PPS_USERLEVELS
112
+ */
113
+ public function getPermissions() {
114
+ return array();
115
+ }
116
+ /**
117
+ * Methods that require nonce to be generated
118
+ * If need - should be redefined in each controller where it required.
119
+ * @return array
120
+ */
121
+ public function getNoncedMethods() {
122
+ return array();
123
+ }
124
+ public function getModule() {
125
+ return framePps::_()->getModule( $this->getCode() );
126
+ }
127
+ protected function _prepareTextLikeSearch($val) {
128
+ return ''; // Should be re-defined for each type
129
+ }
130
+ protected function _prepareModelBeforeListSelect($model) {
131
+ return $model;
132
+ }
133
+ /**
134
+ * Common method for list table data
135
+ */
136
+ public function getListForTbl() {
137
+ $res = new responsePps();
138
+ $res->ignoreShellData();
139
+ $model = $this->getModel();
140
+
141
+ $page = (int) reqPps::getVar('page');
142
+ $rowsLimit = (int) reqPps::getVar('rows');
143
+ $orderBy = reqPps::getVar('sidx');
144
+ $sortOrder = reqPps::getVar('sord');
145
+
146
+ // Our custom search
147
+ $search = reqPps::getVar('search');
148
+ if($search && !empty($search) && is_array($search)) {
149
+ foreach($search as $k => $v) {
150
+ $v = trim($v);
151
+ if(empty($v)) continue;
152
+ if($k == 'text_like') {
153
+ $v = $this->_prepareTextLikeSearch( $v );
154
+ if(!empty($v)) {
155
+ $model->addWhere(array('additionalCondition' => $v));
156
+ }
157
+ } else {
158
+ $model->addWhere(array($k => $v));
159
+ }
160
+ }
161
+ }
162
+ // jqGrid search
163
+ $isSearch = reqPps::getVar('_search');
164
+ if($isSearch) {
165
+ $searchField = trim(reqPps::getVar('searchField'));
166
+ $searchString = trim(reqPps::getVar('searchString'));
167
+ if(!empty($searchField) && !empty($searchString)) {
168
+ // For some cases - we will need to modify search keys and/or values before put it to the model
169
+ $model->addWhere(array(
170
+ $this->_prepareSearchField($searchField) => $this->_prepareSearchString($searchString)
171
+ ));
172
+ }
173
+ }
174
+ $model = $this->_prepareModelBeforeListSelect($model);
175
+ // Get total pages count for current request
176
+ $totalCount = $model->getCount(array('clear' => array('selectFields')));
177
+ $totalPages = 0;
178
+ if($totalCount > 0) {
179
+ $totalPages = ceil($totalCount / $rowsLimit);
180
+ }
181
+ if($page > $totalPages) {
182
+ $page = $totalPages;
183
+ }
184
+ // Calc limits - to get data only for current set
185
+ $limitStart = $rowsLimit * $page - $rowsLimit; // do not put $limit*($page - 1)
186
+ if($limitStart < 0)
187
+ $limitStart = 0;
188
+
189
+ $data = $model
190
+ ->setLimit($limitStart. ', '. $rowsLimit)
191
+ ->setOrderBy( $this->_prepareSortOrder($orderBy) )
192
+ ->setSortOrder( $sortOrder )
193
+ ->setSimpleGetFields()
194
+ ->getFromTbl();
195
+
196
+ $data = $this->_prepareListForTbl( $data );
197
+ $res->addData('page', $page);
198
+ $res->addData('total', $totalPages);
199
+ $res->addData('rows', $data);
200
+ $res->addData('records', $model->getLastGetCount());
201
+ $res = dispatcherPps::applyFilters($this->getCode(). '_getListForTblResults', $res);
202
+ $res->ajaxExec();
203
+ }
204
+ public function removeGroup() {
205
+ $res = new responsePps();
206
+ if($this->getModel()->removeGroup(reqPps::getVar('listIds', 'post'))) {
207
+ $res->addMessage(__('Done', PPS_LANG_CODE));
208
+ } else
209
+ $res->pushError($this->getModel()->getErrors());
210
+ $res->ajaxExec();
211
+ }
212
+ public function clear() {
213
+ $res = new responsePps();
214
+ if($this->getModel()->clear()) {
215
+ $res->addMessage(__('Done', PPS_LANG_CODE));
216
+ } else
217
+ $res->pushError($this->getModel()->getErrors());
218
+ $res->ajaxExec();
219
+ }
220
+ protected function _prepareListForTbl($data) {
221
+ return $data;
222
+ }
223
+ protected function _prepareSearchField($searchField) {
224
+ return $searchField;
225
+ }
226
+ protected function _prepareSearchString($searchString) {
227
+ return $searchString;
228
+ }
229
+ protected function _prepareSortOrder($sortOrder) {
230
+ return $sortOrder;
231
+ }
232
+ }
classes/csvgenerator.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class csvgeneratorPps {
3
+ protected $_filename = '';
4
+ protected $_delimiter = ';';
5
+ protected $_enclosure = "\n";
6
+ protected $_data = array();
7
+ protected $_escape = '\\';
8
+ public function __construct($filename) {
9
+ $this->_filename = $filename;
10
+ }
11
+ public function addCell($x, $y, $value) {
12
+ $this->_data[ $x ][ $y ] = '"'. $value. '"'; //If will not do "" then wymbol for example , will broke file
13
+ }
14
+ public function generate() {
15
+ $strData = '';
16
+ if(!empty($this->_data)) {
17
+ $rows = array();
18
+ foreach($this->_data as $cells) {
19
+ $rows[] = implode($this->_delimiter, $cells);
20
+ }
21
+ $strData = implode($this->_enclosure, $rows);
22
+ }
23
+ filegeneratorPps::_($this->_filename, $strData, 'csv')->generate();
24
+ }
25
+ public function getDelimiter() {
26
+ return $this->_delimiter;
27
+ }
28
+ public function getEnclosure() {
29
+ return $this->_enclosure;
30
+ }
31
+ public function getEscape() {
32
+ return $this->_escape;
33
+ }
34
+ }
35
+
classes/date.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class datePps {
3
+ static public function _($time = NULL) {
4
+ if(is_null($time)) {
5
+ $time = time();
6
+ }
7
+ return date(PPS_DATE_FORMAT_HIS, $time);
8
+ }
9
+ }
classes/db.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Shell - class to work with $wpdb global object
4
+ */
5
+ class dbPps {
6
+ /**
7
+ * Execute query and return results
8
+ * @param string $query query to be executed
9
+ * @param string $get what must be returned - one value (one), one row (row), one col (col) or all results (all - by default)
10
+ * @param const $outputType type of returned data
11
+ * @return mixed data from DB
12
+ */
13
+ static public $query = '';
14
+ static public function get($query, $get = 'all', $outputType = ARRAY_A) {
15
+ global $wpdb;
16
+ $get = strtolower($get);
17
+ $res = NULL;
18
+ $query = self::prepareQuery($query);
19
+ self::$query = $query;
20
+ switch($get) {
21
+ case 'one':
22
+ $res = $wpdb->get_var($query);
23
+ break;
24
+ case 'row':
25
+ $res = $wpdb->get_row($query, $outputType);
26
+ break;
27
+ case 'col':
28
+ $res = $wpdb->get_col($query);
29
+ break;
30
+ case 'all':
31
+ default:
32
+ $res = $wpdb->get_results($query, $outputType);
33
+ break;
34
+ }
35
+ return $res;
36
+ }
37
+ /**
38
+ * Execute one query
39
+ * @return query results
40
+ */
41
+ static public function query($query) {
42
+ global $wpdb;
43
+ return ($wpdb->query( self::prepareQuery($query) ) === false ? false : true);
44
+ }
45
+ /**
46
+ * Get last insert ID
47
+ * @return int last ID
48
+ */
49
+ static public function insertID() {
50
+ global $wpdb;
51
+ return $wpdb->insert_id;
52
+ }
53
+ /**
54
+ * Get number of rows returned by last query
55
+ * @return int number of rows
56
+ */
57
+ static public function numRows() {
58
+ global $wpdb;
59
+ return $wpdb->num_rows;
60
+ }
61
+ /**
62
+ * Replace prefixes in custom query. Suported next prefixes:
63
+ * #__ Worppsess prefix
64
+ * ^__ Store plugin tables prefix (@see PPS_DB_PREF if config.php)
65
+ * @__ Compared of WP table prefix + Store plugin prefix (@example wp_s_)
66
+ * @param string $query query to be executed
67
+ */
68
+ static public function prepareQuery($query) {
69
+ global $wpdb;
70
+ return str_replace(
71
+ array('#__', '^__', '@__'),
72
+ array($wpdb->prefix, PPS_DB_PREF, $wpdb->prefix. PPS_DB_PREF),
73
+ $query);
74
+ }
75
+ static public function getError() {
76
+ global $wpdb;
77
+ return $wpdb->last_error;
78
+ }
79
+ static public function lastID() {
80
+ global $wpdb;
81
+ return $wpdb->insert_id;
82
+ }
83
+ static public function timeToDate($timestamp = 0) {
84
+ if($timestamp) {
85
+ if(!is_numeric($timestamp))
86
+ $timestamp = dateToTimestampPps($timestamp);
87
+ return date('Y-m-d', $timestamp);
88
+ } else {
89
+ return date('Y-m-d');
90
+ }
91
+ }
92
+ static public function dateToTime($date) {
93
+ if(empty($date)) return '';
94
+ if(strpos($date, PPS_DATE_DL)) return dateToTimestampPps($date);
95
+ $arr = explode('-', $date);
96
+ return dateToTimestampPps($arr[2]. PPS_DATE_DL. $arr[1]. PPS_DATE_DL. $arr[0]);
97
+ }
98
+ static public function exist($table, $column = '', $value = '') {
99
+ if(empty($column) && empty($value)) { //Check if table exist
100
+ $res = self::get('SHOW TABLES LIKE "'. $table. '"', 'one');
101
+ } elseif(empty($value)) { //Check if column exist
102
+ $res = self::get('SHOW COLUMNS FROM '. $table. ' LIKE "'. $column. '"', 'one');
103
+ } else { //Check if value in column table exist
104
+ $res = self::get('SELECT COUNT(*) AS total FROM '. $table. ' WHERE '. $column. ' = "'. $value. '"', 'one');
105
+ }
106
+ return !empty($res);
107
+ }
108
+ static public function prepareHtml($d) {
109
+ if(is_array($d)) {
110
+ foreach($d as $i => $el) {
111
+ $d[ $i ] = self::prepareHtml( $el );
112
+ }
113
+ } else {
114
+ $d = esc_html($d);
115
+ }
116
+ return $d;
117
+ }
118
+ static public function prepareHtmlIn($d) {
119
+ if(is_array($d)) {
120
+ foreach($d as $i => $el) {
121
+ $d[ $i ] = self::prepareHtml( $el );
122
+ }
123
+ } else {
124
+ $d = wp_filter_nohtml_kses($d);
125
+ }
126
+ return $d;
127
+ }
128
+ static public function escape($data) {
129
+ global $wpdb;
130
+ return $wpdb->_escape($data);
131
+ }
132
+ static public function getAutoIncrement($table) {
133
+ return (int) self::get('SELECT AUTO_INCREMENT
134
+ FROM information_schema.tables
135
+ WHERE table_name = "'. $table. '"
136
+ AND table_schema = DATABASE( );', 'one');
137
+ }
138
+ static public function setAutoIncrement($table, $autoIncrement) {
139
+ return self::query("ALTER TABLE `". $table. "` AUTO_INCREMENT = ". $autoIncrement. ";");
140
+ }
141
+ }
classes/dispatcher.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class dispatcherPps {
3
+ static protected $_pref = 'pps_';
4
+
5
+ static public function addAction($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
6
+ if(strpos($tag, 'pps_') === false)
7
+ $tag = self::$_pref. $tag;
8
+ return add_action( $tag, $function_to_add, $priority, $accepted_args );
9
+ }
10
+ static public function doAction($tag) {
11
+ if(strpos($tag, 'pps_') === false)
12
+ $tag = self::$_pref. $tag;
13
+ $numArgs = func_num_args();
14
+ if($numArgs > 2) {
15
+ $args = array();
16
+ for($i = 1; $i < $numArgs; $i++) {
17
+ $args[] = func_get_arg($i);
18
+ }
19
+ } elseif($numArgs == 2) {
20
+ $args = func_get_arg(1);
21
+ } else
22
+ $args = NULL;
23
+ return do_action($tag, $args);
24
+ }
25
+ static public function addFilter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
26
+ if(strpos($tag, 'pps_') === false)
27
+ $tag = self::$_pref. $tag;
28
+ return add_filter( $tag, $function_to_add, $priority, $accepted_args );
29
+ }
30
+ static public function applyFilters($tag, $value) {
31
+ if(strpos($tag, 'pps_') === false)
32
+ $tag = self::$_pref. $tag;
33
+ if(func_num_args() > 2) {
34
+ $args = array($tag);
35
+ for($i = 1; $i < func_num_args(); $i++) {
36
+ $args[] = func_get_arg($i);
37
+ }
38
+ return call_user_func_array('apply_filters', $args);
39
+ } else {
40
+ return apply_filters( $tag, $value );
41
+ }
42
+ }
43
+ }
classes/errors.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class errorsPps {
3
+ const FATAL = 'fatal';
4
+ const MOD_INSTALL = 'mod_install';
5
+ static private $errors = array();
6
+ static private $haveErrors = false;
7
+
8
+ static public $current = array();
9
+ static public $displayed = false;
10
+
11
+ static public function push($error, $type = 'common') {
12
+ if(!isset(self::$errors[$type]))
13
+ self::$errors[$type] = array();
14
+ if(is_array($error))
15
+ self::$errors[$type] = array_merge(self::$errors[$type], $error);
16
+ else
17
+ self::$errors[$type][] = $error;
18
+ self::$haveErrors = true;
19
+
20
+ if($type == 'session')
21
+ self::setSession(self::$errors[$type]);
22
+ }
23
+ static public function setSession($error) {
24
+ $sesErrors = self::getSession();
25
+ if(empty($sesErrors))
26
+ $sesErrors = array();
27
+ if(is_array($error))
28
+ $sesErrors = array_merge($sesErrors, $error);
29
+ else
30
+ $sesErrors[] = $error;
31
+ reqPps::setVar('sesErrors', $sesErrors, 'session');
32
+ }
33
+ static public function init() {
34
+ $ppsErrors = reqPps::getVar('ppsErrors');
35
+ if(!empty($ppsErrors)) {
36
+ if(!is_array($ppsErrors)) {
37
+ $ppsErrors = array( $ppsErrors );
38
+ }
39
+ $ppsErrors = array_map('htmlspecialchars', array_map('stripslashes', array_map('trim', $ppsErrors)));
40
+ if(!empty($ppsErrors)) {
41
+ self::$current = $ppsErrors;
42
+ if(is_admin()) {
43
+ add_action('admin_notices', array('errorsPps', 'showAdminErrors'));
44
+ } else {
45
+ add_filter('the_content', array('errorsPps', 'appendErrorsContent'), 99999);
46
+ }
47
+ }
48
+ }
49
+ }
50
+ static public function showAdminErrors() {
51
+ if(self::$current) {
52
+ $html = '';
53
+ foreach(self::$current as $error) {
54
+ $html .= '<div class="error"><p><strong style="font-size: 15px;">'. $error. '</strong></p></div>';
55
+ }
56
+ echo $html;
57
+ }
58
+ }
59
+ static public function appendErrorsContent($content) {
60
+ if(!self::$displayed && !empty(self::$current)) {
61
+ $content = '<div class="toeErrorMsg">'. implode('<br />', self::$current). '</div>'. $content;
62
+ self::$displayed = true;
63
+ }
64
+ return $content;
65
+ }
66
+ static public function getSession() {
67
+ return reqPps::getVar('sesErrors', 'session');
68
+ }
69
+ static public function clearSession() {
70
+ reqPps::clearVar('sesErrors', 'session');
71
+ }
72
+ static public function get($type = '') {
73
+ $res = array();
74
+ if(!empty(self::$errors)) {
75
+ if(empty($type)) {
76
+ foreach(self::$errors as $e) {
77
+ foreach($e as $error) {
78
+ $res[] = $error;
79
+ }
80
+ }
81
+ } else
82
+ $res = self::$errors[$type];
83
+ }
84
+ return $res;
85
+ }
86
+ static public function haveErrors($type = '') {
87
+ if(empty($type))
88
+ return self::$haveErrors;
89
+ else
90
+ return isset(self::$errors[$type]);
91
+ }
92
+ }
93
+
classes/field.php ADDED
@@ -0,0 +1,518 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class fieldPps {
3
+ public $name = '';
4
+ public $html = '';
5
+ public $type = '';
6
+ public $default = '';
7
+ public $value = '';
8
+ public $label = '';
9
+ public $maxlen = 0;
10
+ public $id = 0;
11
+ public $htmlParams = array();
12
+ public $validate = array();
13
+ public $description = '';
14
+ /**
15
+ * Wheter or not add error html element right after input field
16
+ * if bool - will be added standard element
17
+ * if string - it will be add this string
18
+ */
19
+ public $errorEl = false;
20
+ /**
21
+ * Name of method in table object to prepare data before insert / update operations
22
+ */
23
+ public $adapt = array('htmlPps' => '', 'dbFrom' => '', 'dbTo' => '');
24
+ /**
25
+ * Init database field representation
26
+ * @param string $html html type of field (text, textarea, etc. @see html class)
27
+ * @param string $type database type (int, varcahr, etc.)
28
+ * @param mixed $default default value for this field
29
+ */
30
+ public function __construct($name, $html = 'text', $type = 'other', $default = '', $label = '', $maxlen = 0, $adaption = array(), $validate = '', $description = '') {
31
+ $this->name = $name;
32
+ $this->html = $html;
33
+ $this->type = $type;
34
+ $this->default = $default;
35
+ $this->value = $default; //Init field value same as default
36
+ $this->label = $label;
37
+ $this->maxlen = $maxlen;
38
+ $this->description = $description;
39
+ if($adaption)
40
+ $this->adapt = $adaption;
41
+ if($validate) {
42
+ $this->setValidation($validate);
43
+ }
44
+ if($type == 'varchar' && !empty($maxlen) && !in_array('validLen', $this->validate)) {
45
+ $this->addValidation('validLen');
46
+ }
47
+ }
48
+ /**
49
+ * @param mixed $errorEl - if bool and "true" - than we will use standard error element, if string - we will use this string as error element
50
+ */
51
+ public function setErrorEl($errorEl) {
52
+ $this->errorEl = $errorEl;
53
+ }
54
+ public function getErrorEl() {
55
+ return $this->errorEl;
56
+ }
57
+ public function setValidation($validate) {
58
+ if(is_array($validate))
59
+ $this->validate = $validate;
60
+ else {
61
+ if(strpos($validate, ','))
62
+ $this->validate = array_map('trim', explode(',', $validate));
63
+ else
64
+ $this->validate = array(trim($validate));
65
+ }
66
+ }
67
+ public function addValidation($validate) {
68
+ $this->validate[] = $validate;
69
+ }
70
+ /**
71
+ * Set $value property.
72
+ * Sure - it is public and can be set directly, but it can be more
73
+ * comfortable to use this method in future
74
+ * @param mixed $value value to be set
75
+ */
76
+ public function setValue($value, $fromDB = false) {
77
+ if(isset($this->adapt['dbFrom']) && $this->adapt['dbFrom'] && $fromDB)
78
+ $value = fieldAdapterPps::_($value, $this->adapt['dbFrom'], fieldAdapterPps::DB);
79
+ $this->value = $value;
80
+ }
81
+ public function setLabel($label) {
82
+ $this->label = $label;
83
+ }
84
+ public function setHtml($html) {
85
+ $this->html = $html;
86
+ }
87
+ public function getHtml() {
88
+ return $this->html;
89
+ }
90
+ public function setName($name) {
91
+ $this->name = $name;
92
+ }
93
+ public function getName() {
94
+ return $this->name;
95
+ }
96
+ public function getValue() {
97
+ return $this->value;
98
+ }
99
+ public function getLabel() {
100
+ return $this->label;
101
+ }
102
+ public function setID($id) {
103
+ $this->id = $id;
104
+ }
105
+ public function getID() {
106
+ return $this->id;
107
+ }
108
+ public function setAdapt($adapt) {
109
+ $this->adapt = $adapt;
110
+ }
111
+ public function drawHtml($tag, $id) {
112
+ if(method_exists('htmlPps', $this->html)) {
113
+ $method = $this->html;
114
+ //echo $this->name. ': '. $this->value. '<br />';
115
+ if(!empty($this->value))
116
+ $this->htmlParams['value'] = $this->value;
117
+ if ($method == 'checkbox') {
118
+ if ($this->value == 1) {
119
+ $this->htmlParams['checked'] = 1;
120
+ }
121
+ }
122
+ if($this->adapt['html']) {
123
+ fieldAdapterPps::_($this, $this->adapt['html'], fieldAdapterPps::HTML);
124
+ }
125
+ $params = $this->processParams($tag, $id);
126
+ if ($params != '')
127
+ return $params;
128
+ if ($this->name == 'default_value') {
129
+ $optionsFromDb = framePps::_()->getModule('optionsPps')->getHelper()->getOptions($id);
130
+ if (!empty($optionsFromDb)) {
131
+ $options = array(0 => __('Select', PPS_LANG_CODE));
132
+ foreach($optionsFromDb as $k => $v)
133
+ $options[$k] = $v;
134
+ $method = 'selectbox';
135
+ $this->htmlParams['optionsPps'] = $options;
136
+ }
137
+ }
138
+ $htmlContent = htmlPps::$method($this->name, $this->htmlParams);
139
+ if(!empty($this->errorEl)) {
140
+ if(is_bool($this->errorEl))
141
+ $errorEl = '<div class="toeErrorForField toe_'. htmlPps::nameToClassId($this->name). '"></div>';
142
+ else //if it is string
143
+ $errorEl = $this->errorEl;
144
+ $htmlContent .= $errorEl;
145
+ }
146
+ return $htmlContent;
147
+ }
148
+ return false;
149
+ }
150
+ public function displayValue() {
151
+ $value = '';
152
+ switch($this->html) {
153
+ case 'countryList':
154
+ $value = fieldAdapterPps::displayCountry($this->value);
155
+ break;
156
+ case 'statesList':
157
+ $value = fieldAdapterPps::displayState($this->value);
158
+ break;
159
+ case 'checkboxlist':
160
+ $options = $this->getHtmlParam('optionsPps');
161
+ $value = array();
162
+ if(!empty($options) && is_array($options)) {
163
+ foreach($options as $opt) {
164
+ if(isset($opt['checked']) && $opt['checked']) {
165
+ $value[] = $opt['text'];
166
+ }
167
+ }
168
+ }
169
+ if(empty($value))
170
+ $value = __('N/A', PPS_LANG_CODE);
171
+ else
172
+ $value = implode('<br />', $value);
173
+ break;
174
+ case 'selectbox': case 'radiobuttons':
175
+ $options = $this->getHtmlParam('optionsPps');
176
+ if(!empty($options) && !empty($options[ $this->value ])) {
177
+ $value = $options[ $this->value ];
178
+ } else {
179
+ $value = __('N/A', PPS_LANG_CODE);
180
+ }
181
+ break;
182
+ default:
183
+ if ($this->value == '') {
184
+ $value = __('N/A', PPS_LANG_CODE);
185
+ } else {
186
+ if(is_array($this->value)) {
187
+ $options = $this->getHtmlParam('optionsPps');
188
+ if(!empty($options) && is_array($options)) {
189
+ $valArr = array();
190
+ foreach($this->value as $v) {
191
+ $valArr[] = $options[$v];
192
+ }
193
+ $value = recImplode('<br />', $valArr);
194
+ } else {
195
+ $value = recImplode('<br />', $this->value);
196
+ }
197
+ } else
198
+ $value = $this->value;
199
+ }
200
+ break;
201
+ }
202
+ if($echo)
203
+ echo $value;
204
+ else
205
+ return $value;
206
+ }
207
+ public function showValue() {
208
+ echo $this->displayValue();
209
+ }
210
+ public function display($tag = 1, $id = 0) {
211
+ echo $this->drawHtml($tag, $id);
212
+ }
213
+ public function addHtmlParam($name, $value) {
214
+ $this->htmlParams[$name] = $value;
215
+ }
216
+ /**
217
+ * Alias for addHtmlParam();
218
+ */
219
+ public function setHtmlParam($name, $value) {
220
+ $this->addHtmlParam($name, $value);
221
+ }
222
+ public function setHtmlParams($params) {
223
+ $this->htmlParams = $params;
224
+ }
225
+ public function getHtmlParam($name) {
226
+ return isset($this->htmlParams[$name]) ? $this->htmlParams[$name] : false;
227
+ }
228
+ /**
229
+ * Function to display userfields in front-end
230
+ *
231
+ * @param string $name
232
+ * @param mixed $fieldValue
233
+ * @return string
234
+ */
235
+ public function viewField($name, $fieldValue = '') {
236
+ $method = $this->html;
237
+ $options = framePps::_()->getModule('optionsPps')->getHelper()->getOptions($this->id);
238
+ $attrs = '';
239
+ if (is_object($this->htmlParams['attr']) && count($this->htmlParams['attr']) > 0) {
240
+ foreach ($this->htmlParams['attr'] as $attribute=>$value) {
241
+ if ($value != '') {
242
+ $attrs .= $attribute.'="'.$value.'" ';
243
+ }
244
+ }
245
+ }
246
+ if ($fieldValue == $this->default_value) {
247
+ $checked = 1;
248
+ } else {
249
+ $checked = 0;
250
+ }
251
+ if ($fieldValue == '') {
252
+ $fieldValue = $this->default_value;
253
+ }
254
+ $params = array('optionsPps'=>$options, 'attrs' => $attrs, 'value' => $fieldValue, 'checked' => $checked);
255
+ $output = '';
256
+ if(method_exists('htmlPps', $method)) {
257
+ $output .= htmlPps::$method($name, $params);
258
+ $output .= htmlPps::hidden('extra_field['.$this->name.']',array('value'=>$this->id));
259
+ }
260
+ return $output;
261
+ }
262
+
263
+ /**
264
+ * Function to process field params
265
+ */
266
+ public function processParams($tag, $id){
267
+ return '';
268
+ if ($this->name == "params") {
269
+ if(is_array($this->value) || is_object($this->value)) {
270
+ $params = $this->value;
271
+ } else {
272
+ $params = json_decode($this->value);
273
+ }
274
+ $add_option = '';
275
+ switch ($tag) {
276
+ case 5:
277
+ $add_option = __('Add Checkbox', PPS_LANG_CODE);
278
+ $options_tag = '';
279
+ $image_tag = ' style="display:none"';
280
+ break;
281
+ case 9:
282
+ $add_option = __('Add Item', PPS_LANG_CODE);
283
+ $options_tag = '';
284
+ $image_tag = ' style="display:none"';
285
+ break;
286
+ case 12:
287
+ $add_option = __('Add Item', PPS_LANG_CODE);
288
+ $options_tag = '';
289
+ $image_tag = ' style="display:none"';
290
+ break;
291
+ case 10:
292
+ $options_tag = '';
293
+ $add_option = __('Add Radio Button', PPS_LANG_CODE);
294
+ $image_tag = ' style="display:none"';
295
+ break;
296
+ case 8:
297
+ $image_tag = '';
298
+ $options_tag = ' style="display:none"';
299
+ break;
300
+ default:
301
+ $options_tag = ' style="display:none"';
302
+ $image_tag = ' style="display:none"';
303
+ break;
304
+ }
305
+ if ($tag > 0 || $id == 0) {
306
+ $output .= '<div class="options options_tag"'.$options_tag.'>';
307
+ $output .= '<span class="add_option">'.$add_option.'</span>';
308
+ $output .= fieldAdapterPps::_($id,'getExtraFieldOptions',fieldAdapterPps::STR);
309
+ $output .= '</div>';
310
+
311
+ $output .= '<div class="options image_tag"'.$image_tag.'>'.__('Dimensions', PPS_LANG_CODE).':<br />';
312
+ $params->width?$width = $params->width:'';
313
+ $params->height?$height = $params->height:'';
314
+ $output .= __('width', PPS_LANG_CODE).':<br />';
315
+ $output .= htmlPps::text('params[width]',array('value'=>$width)).'<br />';
316
+ $output .= __('height', PPS_LANG_CODE).':<br />';
317
+ $output .= htmlPps::text('params[height]',array('value'=>$height)).'<br />';
318
+ $output .= '</div>';
319
+ }
320
+ if($this->adapt['htmlParams']) {
321
+ $output .= fieldAdapterPps::_($this, $this->adapt['htmlParams'], fieldAdapterPps::STR);
322
+ } else {
323
+ $output .= '<a href="javascript:void(0);" class="set_properties">'.__('Click to set field "id" and "class"', PPS_LANG_CODE).'</a>';
324
+ $output .= '<div class="attributes" style="display:none;">'.__('Attributes', PPS_LANG_CODE).':<br />';
325
+ $output .= fieldAdapterPps::_($params,'getFieldAttributes', fieldAdapterPps::STR);
326
+ $output .= '</div>';
327
+ }
328
+ return $output;
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Check if the element exists in array
334
+ * @param array $param
335
+ */
336
+ function checkVarFromParam($param, $element) {
337
+ return utilsPps::xmlAttrToStr($param, $element);
338
+ /*if (isset($param[$element])) {
339
+ // convert object element to string
340
+ return (string)$param[$element];
341
+ } else {
342
+ return '';
343
+ }*/
344
+ }
345
+
346
+ /**
347
+ * Prepares configuration options
348
+ *
349
+ * @param file $xml
350
+ * @return array $config_params
351
+ */
352
+ public function prepareConfigOptions($xml) {
353
+ // load xml structure of parameters
354
+ $config = simplexml_load_file($xml);
355
+ $config_params = array();
356
+ foreach ($config->params->param as $param) {
357
+ // read the variables
358
+ $name = $this->checkVarFromParam($param,'name');
359
+ $type = $this->checkVarFromParam($param,'type');
360
+ $label = $this->checkVarFromParam($param,'label');
361
+ $helper = $this->checkVarFromParam($param,'helperPps');
362
+ $module = $this->checkVarFromParam($param,'modulePps');
363
+ $values = $this->checkVarFromParam($param,'values');
364
+ $default = $this->checkVarFromParam($param,'default');
365
+ $description = $this->checkVarFromParam($param,'description');
366
+ if ($name == '') continue;
367
+ // fill in the variables to configuration array
368
+ $config_params[$name] = array('type'=>$type,
369
+ 'label'=>$label,
370
+ 'helperPps'=>$helper,
371
+ 'modulePps'=>$module,
372
+ 'values'=>$values,
373
+ 'default'=>$default,
374
+ 'description'=>$description,
375
+ );
376
+ }
377
+ return $config_params;
378
+ }
379
+ public function setDescription($desc) {
380
+ $this->description = $desc;
381
+ }
382
+ public function getDescription() {
383
+ return $this->description;
384
+ }
385
+ /**
386
+ * Displays the config options for given module
387
+ *
388
+ * @param string $module
389
+ * @param array $addDefaultOptions - if you want to add some additionsl options - specify it here
390
+ */
391
+ public function drawConfig($module, $additionalOptions = array()) {
392
+ if(!framePps::_()->getModule($module))
393
+ return false;
394
+ // check for xml file with params structure
395
+ if(framePps::_()->getModule($module)->isExternal())
396
+ $config_xml = framePps::_()->getModule($module)->getModDir(). 'mod.xml';
397
+ else
398
+ $config_xml = PPS_MODULES_DIR.$module.DS.'mod.xml';
399
+
400
+ if (!file_exists($config_xml)) {
401
+ // if there is no configuration file for this $module
402
+ return __('There are no configuration options for this module', PPS_LANG_CODE);
403
+ }
404
+ $output = '';
405
+ // reading params structure
406
+ $configOptions = $this->prepareConfigOptions($config_xml);
407
+ // reading params from database
408
+ //bugodel2nia..............
409
+ if(is_string($this->value))
410
+ $params = Utils::jsonDecode($this->value);
411
+ elseif(is_object($this->value) || is_array($this->value))
412
+ $params = toeObjectToArray($this->value);
413
+ //if (!empty($params)) {
414
+ if (!empty($configOptions)){
415
+ $i = 0;
416
+ if (empty($params)) {
417
+ $params = array('0'=>array());
418
+ }
419
+ if(is_array($additionalOptions) && !empty($additionalOptions)) {
420
+ $configOptions = array_merge($configOptions, $additionalOptions);
421
+ }
422
+ foreach ($params as $param) {
423
+ $output .= '<div class="module_options">';
424
+ foreach ($configOptions as $key=>$value){
425
+ $fieldValue = '';
426
+ $output .= '<div class="module_option">';
427
+ $method = $configOptions[$key]['type'];
428
+ $name = 'params['.$i.']['.$key.']';
429
+ $options = array();
430
+ // if the values attribute is set
431
+ if ($configOptions[$key]['values'] != ''){
432
+ $extract_options = explode(',', $configOptions[$key]['values']);
433
+ if (count($extract_options) > 1) {
434
+ foreach ($extract_options as $item=>$string) {
435
+ if(strpos($string, '=>')) {
436
+ $keyVal = array_map('trim', explode('=>', $string));
437
+ $options[ $keyVal[0] ] = $keyVal[1];
438
+ } else {
439
+ $options[$string] = $string;
440
+ }
441
+ }
442
+ } else {
443
+ $fieldValue = $configOptions[$key]['default'];
444
+ }
445
+ // if helper is needed to render the object
446
+ } elseif ($configOptions[$key]['helper'] != '') {
447
+ $helper_name = $configOptions[$key]['helper'];
448
+ // is helper from current module or other?
449
+ if ($configOptions[$key]['module'] != '') {
450
+ $hmodule = $configOptions[$key]['module'];
451
+ } else {
452
+ $hmodule = $module;
453
+ }
454
+ // calling the helper class
455
+ $helper = framePps::_()->getModule($hmodule)->getHelper();
456
+ if ($helper) {
457
+ // calling the helper method for current option
458
+ if (method_exists($helper, $helper_name))
459
+ $options = $helper->$helper_name();
460
+ }
461
+ }
462
+ if (isset($param[$key])) {
463
+ $fieldValue = $param[$key];
464
+ } else {
465
+ if ($fieldValue == '')
466
+ $fieldValue = $configOptions[$key]['default'];
467
+ }
468
+ // filling the parameters to build html element
469
+ $htmlParams = array('value'=>$fieldValue,'optionsPps'=>$options);
470
+ if($method == 'checkbox') {
471
+ $htmlParams['value'] = 1;
472
+ $htmlParams['checked'] = (bool)$fieldValue;
473
+ }
474
+ if(!empty($configOptions[$key]['htmlParams']) && is_array($configOptions[$key]['htmlParams'])) {
475
+ $htmlParams = array_merge($htmlParams, $configOptions[$key]['htmlParams']);
476
+ }
477
+ // output label and html element
478
+ $output .= '<label>'.__($configOptions[$key]['label']);
479
+ if ($configOptions[$key]['description'] != '') {
480
+ $output .= '<a class="toeOptTip" tip="'.__($configOptions[$key]['description']).'"></a>';
481
+ }
482
+ $output .= '</label><br />';
483
+ $output .= htmlPps::$method($name,$htmlParams).'<br />';
484
+ $output .= '</div>';
485
+ }
486
+ $i++;
487
+ $output .= '</div>';
488
+ }
489
+ }
490
+ return $output;
491
+ }
492
+
493
+ public function displayConfig($module) {
494
+ echo $this->drawConfig($module);
495
+ }
496
+ /**
497
+ * This method will prepare internal value to it's type
498
+ * @see $this->type
499
+ * @return mixed - prepared value on the basis of $this->type
500
+ */
501
+ public function valToType() {
502
+ switch($this->type) {
503
+ case 'int':
504
+ case 'mediumint':
505
+ case 'smallint':
506
+ $this->value = (int) $this->value;
507
+ break;
508
+ case 'float':
509
+ $this->value = (float) $this->value;
510
+ break;
511
+ case 'double':
512
+ case 'decimal':
513
+ $this->value = (double) $this->value;
514
+ break;
515
+ }
516
+ return $this->type;
517
+ }
518
+ }
classes/fieldAdapter.php ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class to adapt field before display
4
+ * return ONLY htmlParams property
5
+ * @see field
6
+ */
7
+ class fieldAdapterPps {
8
+ const DB = 'dbPps';
9
+ const HTML = 'htmlPps';
10
+ const STR = 'str';
11
+ static public $userfieldDest = array('registration', 'shipping', 'billing');
12
+ static public $countries = array();
13
+ static public $states = array();
14
+ /**
15
+ * Executes field Adaption process
16
+ * @param object type field or value $fieldOrValue if DB adaption - this must be a value of field, elase if html - field object
17
+ */
18
+ static public function _($fieldOrValue, $method, $type) {
19
+ if(method_exists('fieldAdapterPps', $method)) {
20
+ switch($type) {
21
+ case self::DB:
22
+ return self::$method($fieldOrValue);
23
+ break;
24
+ case self::HTML:
25
+ self::$method($fieldOrValue);
26
+ break;
27
+ case self::STR:
28
+ return self::$method($fieldOrValue);
29
+ break;
30
+ }
31
+ }
32
+ return $fieldOrValue;
33
+ }
34
+ static public function userFieldDestHtml($field) {
35
+ $field->htmlParams['optionsPps'] = array();
36
+ if(!is_array($field->value)) {
37
+ if(empty($field->value))
38
+ $field->value = array();
39
+ else
40
+ $field->value = json_decode($field->value);
41
+ }
42
+ foreach(self::$userfieldDest as $d) {
43
+ $field->htmlParams['optionsPps'][] = array(
44
+ 'id' => $d,
45
+ 'text' => $d,
46
+ 'checked' => in_array($d, $field->value)
47
+ );
48
+ }
49
+ }
50
+ static public function userFieldDestToDB($value) {
51
+ return utilsPps::jsonEncode($value);
52
+ }
53
+ static public function userFieldDestFromDB($value) {
54
+ return utilsPps::jsonDecode($value);
55
+ }
56
+ static public function taxDataHtml($field) {
57
+ $listOfDest = array();
58
+ if(!is_array($field->value)) {
59
+ if(empty($field->value))
60
+ $field->value = array();
61
+ else
62
+ $field->value = (array)json_decode($field->value, true);
63
+ }
64
+ foreach(self::$userfieldDest as $d) {
65
+ $listOfDest[] = array(
66
+ 'id' => $d,
67
+ 'text' => $d,
68
+ 'checked' => (is_array($field->value['dest']) && in_array($d, $field->value['dest']))
69
+ );
70
+ }
71
+ $categories = framePps::_()->getModule('products')->getCategories();
72
+ $brands = framePps::_()->getModule('products')->getBrands();
73
+ $cOptions = array();
74
+ $bOptions = array();
75
+ if(!empty($categories)) {
76
+ if(!is_array($field->value['categories']))
77
+ $field->value['categories'] = array();
78
+ foreach($categories as $c) {
79
+ $cOptions[] = array('id' => $c->term_taxonomy_id,
80
+ 'text' => $c->cat_name,
81
+ 'checked' => in_array($c->term_taxonomy_id, $field->value['categories']));
82
+ }
83
+ }
84
+ if(!empty($brands)) {
85
+ if(!is_array($field->value['brands']))
86
+ $field->value['brands'] = array();
87
+ foreach($brands as $b) {
88
+ $bOptions[] = array('id' => $b->term_taxonomy_id,
89
+ 'text' => $b->cat_name,
90
+ 'checked' => in_array($b->term_taxonomy_id, $field->value['brands']));
91
+ }
92
+ }
93
+ return '<div>'. __('Apply To', PPS_LANG_CODE). '
94
+ <div id="tax_address">
95
+ <b>'. __('Address', PPS_LANG_CODE). '</b><br />
96
+ '. __('Destination', PPS_LANG_CODE). ':'. htmlPps::checkboxlist('params[dest]', array('optionsPps' => $listOfDest)). '<br />
97
+ '. __('Country', PPS_LANG_CODE). ':'. htmlPps::countryList('params[country]', array('notSelected' => true, 'value' => $field->value['country'])). '<br />
98
+ </div>
99
+ <div id="tax_category">
100
+ <b>'. __('Categories', PPS_LANG_CODE). '</b><br />
101
+ '. (empty($cOptions) ? __('You have no categories', PPS_LANG_CODE) : htmlPps::checkboxlist('params[categories][]', array('optionsPps' => $cOptions))). '<br />
102
+ <b>'. __('Brands', PPS_LANG_CODE). '</b><br />
103
+ '. (empty($bOptions) ? __('You have no brands', PPS_LANG_CODE) : htmlPps::checkboxlist('params[brands][]', array('optionsPps' => $bOptions))). '<br />
104
+ </div>
105
+ <div>'. __('Tax Rate', PPS_LANG_CODE).': '. htmlPps::text('params[rate]', array('value' => $field->value['rate'])).'</div>
106
+ <div>'. __('Absolute', PPS_LANG_CODE).': '. htmlPps::checkbox('params[absolute]', array('checked' => $field->value['absolute'])).'</div>
107
+ </div>';
108
+ }
109
+ static public function displayCountry($cid, $key = 'name') {
110
+ if($key == 'name') {
111
+ $countries = self::getCountries();
112
+ return $countries[$cid];
113
+ } else {
114
+ if(empty(self::$countries))
115
+ self::$countries = self::getCachedCountries();
116
+ foreach(self::$countries as $c) {
117
+ if($c['id'] == $cid)
118
+ return $c[ $key ];
119
+ }
120
+ }
121
+ return false;
122
+ }
123
+ static public function displayState($sid, $key = 'name') {
124
+ $states = self::getStates();
125
+ return empty($states[$sid]) ? $sid : $states[$sid][$key];
126
+ }
127
+ static public function getCountries($notSelected = false) {
128
+ static $options = array();
129
+ if(empty($options[ $notSelected ])) {
130
+ $options[ $notSelected ] = array();
131
+ if(empty(self::$countries))
132
+ self::$countries = self::getCachedCountries();
133
+ if($notSelected) {
134
+ $options[ $notSelected ][0] = is_bool($notSelected) ? __('Not selected', PPS_LANG_CODE) : __($notSelected);
135
+ }
136
+ foreach(self::$countries as $c) $options[ $notSelected ][$c['id']] = $c['name'];
137
+ }
138
+ return $options[ $notSelected ];
139
+ }
140
+ static public function getStates($notSelected = false) {
141
+ static $options = array();
142
+ if(empty($options[ $notSelected ])) {
143
+ $options[ $notSelected ] = array();
144
+ if(empty(self::$states))
145
+ self::$states = self::getCachedStates();
146
+ if($notSelected) {
147
+ $notSelectedLabel = is_bool($notSelected) ? 'Not selected' : $notSelected;
148
+ $options[ $notSelected ][0] = array('name' => __( $notSelectedLabel ), 'country_id' => NULL);
149
+ }
150
+ foreach(self::$states as $s) $options[ $notSelected ][$s['id']] = $s;
151
+ }
152
+ return $options[ $notSelected ];
153
+ }
154
+ /**
155
+ * Function to get extra field options
156
+ *
157
+ * @param object $field
158
+ * @return string
159
+ */
160
+ static public function getExtraFieldOptions($field_id) {
161
+ $output = '';
162
+ if ($field_id == 0) return '';
163
+ $options = framePps::_()->getModule('optionsPps')->getHelper()->getOptions($field_id);
164
+ if (!empty($options)) {
165
+ foreach ($options as $key=>$value) {
166
+ $output .= '<p>'.$value.'<span class="delete_option" rel="'.$key.'"></span></p>';
167
+ }
168
+ }
169
+ return $output;
170
+ }
171
+ /**
172
+ * Function to get field params
173
+ *
174
+ * @param object $params
175
+ */
176
+ static public function getFieldAttributes($params){
177
+ $output = '';
178
+ if (!empty($params->attr)) {
179
+ foreach ($params->attr as $key=>$value) {
180
+ $output .= __($key).':<br />';
181
+ $output .= htmlPps::text('params[attr]['.$key.']',array('value'=>$value)).'<br />';
182
+ }
183
+ } else {
184
+ $output .= __('class', PPS_LANG_CODE).':<br />';
185
+ $output .= htmlPps::text('params[attr][class]',array('value'=>'')).'<br />';
186
+ $output .= __('id', PPS_LANG_CODE).':<br />';
187
+ $output .= htmlPps::text('params[attr][id]',array('value'=>'')).'<br />';
188
+ }
189
+ return $output;
190
+ }
191
+ /**
192
+ * Generating the list of categories for product extra fields
193
+ *
194
+ * @param object $field
195
+ */
196
+ static function productFieldCategories($field){
197
+ if(!empty($field->htmlParams['optionsPps']))
198
+ return;
199
+ /*$field->htmlParams['attrs'] = 'id="select_product_field_cat" rel="0"';
200
+ $field->htmlParams['optionsPps'] = array();
201
+ $categories = framePps::_()->getModule('products')->getCategories();
202
+ if(!empty($categories)) {
203
+ if(!is_array($field->value['categories']))
204
+ $field->value['categories'] = array();
205
+ $field->htmlParams['optionsPps'][0] = in_array(0,$field->value['categories'])?__('Deselect All'):__('Select All', PPS_LANG_CODE);
206
+ foreach($categories as $c) {
207
+ $field->htmlParams['optionsPps'][$c->term_taxonomy_id] = $c->cat_name;
208
+ }
209
+ }*/
210
+ }
211
+ static public function intToDB($val) {
212
+ return intval($val);
213
+ }
214
+ static public function floatToDB($val) {
215
+ return floatval($val);
216
+ }
217
+ /**
218
+ * Save this in static var - to futher usage
219
+ * @return array with countries
220
+ */
221
+ static public function getCachedCountries($clearCache = false) {
222
+ if(empty(self::$countries) || $clearCache)
223
+ self::$countries = framePps::_()->getTable('countries')->getAll('id, name, iso_code_2, iso_code_3');
224
+ return self::$countries;
225
+ }
226
+ /**
227
+ * Save this in static var - to futher usage
228
+ * @return array with states
229
+ */
230
+ static public function getCachedStates($clearCache = false) {
231
+ if(empty(self::$states) || $clearCache)
232
+ self::$states = framePps::_()->getTable('states')
233
+ ->leftJoin( framePps::_()->getTable('countries'), 'country_id' )
234
+ ->getAll('toe_states.id,
235
+ toe_states.name,
236
+ toe_states.code,
237
+ toe_states.country_id,
238
+ toe_cry.name AS c_name,
239
+ toe_cry.iso_code_2 AS c_iso_code_2,
240
+ toe_cry.iso_code_3 AS c_iso_code_3');
241
+ return self::$states;
242
+ }
243
+ static public function getFontsList() {
244
+ return array("Abel", "Abril Fatface", "Aclonica", "Acme", "Actor", "Adamina", "Advent Pro",
245
+ "Aguafina Script", "Aladin", "Aldrich", "Alegreya", "Alegreya SC", "Alex Brush", "Alfa Slab One", "Alice",
246
+ "Alike", "Alike Angular", "Allan", "Allerta", "Allerta Stencil", "Allura", "Almendra", "Almendra SC", "Amaranth",
247
+ "Amatic SC", "Amethysta", "Andada", "Andika", "Angkor", "Annie Use Your Telescope", "Anonymous Pro", "Antic",
248
+ "Antic Didone", "Antic Slab", "Anton", "Arapey", "Arbutus", "Architects Daughter", "Arimo", "Arizonia", "Armata",
249
+ "Artifika", "Arvo", "Asap", "Asset", "Astloch", "Asul", "Atomic Age", "Aubrey", "Audiowide", "Average",
250
+ "Averia Gruesa Libre", "Averia Libre", "Averia Sans Libre", "Averia Serif Libre", "Bad Script", "Balthazar",
251
+ "Bangers", "Basic", "Battambang", "Baumans", "Bayon", "Belgrano", "Belleza", "Bentham", "Berkshire Swash",
252
+ "Bevan", "Bigshot One", "Bilbo", "Bilbo Swash Caps", "Bitter", "Black Ops One", "Bokor", "Bonbon", "Boogaloo",
253
+ "Bowlby One", "Bowlby One SC", "Brawler", "Bree Serif", "Bubblegum Sans", "Buda", "Buenard", "Butcherman",
254
+ "Butterfly Kids", "Cabin", "Cabin Condensed", "Cabin Sketch", "Caesar Dressing", "Cagliostro", "Calligraffitti",
255
+ "Cambo", "Candal", "Cantarell", "Cantata One", "Cardo", "Carme", "Carter One", "Caudex", "Cedarville Cursive",
256
+ "Ceviche One", "Changa One", "Chango", "Chau Philomene One", "Chelsea Market", "Chenla", "Cherry Cream Soda",
257
+ "Chewy", "Chicle", "Chivo", "Coda", "Coda Caption", "Codystar", "Comfortaa", "Coming Soon", "Concert One",
258
+ "Condiment", "Content", "Contrail One", "Convergence", "Cookie", "Copse", "Corben", "Cousine", "Coustard",
259
+ "Covered By Your Grace", "Crafty Girls", "Creepster", "Crete Round", "Crimson Text", "Crushed", "Cuprum", "Cutive",
260
+ "Damion", "Dancing Script", "Dangrek", "Dawning of a New Day", "Days One", "Delius", "Delius Swash Caps",
261
+ "Delius Unicase", "Della Respira", "Devonshire", "Didact Gothic", "Diplomata", "Diplomata SC", "Doppio One",
262
+ "Dorsa", "Dosis", "Dr Sugiyama", "Droid Sans", "Droid Sans Mono", "Droid Serif", "Duru Sans", "Dynalight",
263
+ "EB Garamond", "Eater", "Economica", "Electrolize", "Emblema One", "Emilys Candy", "Engagement", "Enriqueta",
264
+ "Erica One", "Esteban", "Euphoria Script", "Ewert", "Exo", "Expletus Sans", "Fanwood Text", "Fascinate", "Fascinate Inline",
265
+ "Federant", "Federo", "Felipa", "Fjord One", "Flamenco", "Flavors", "Fondamento", "Fontdiner Swanky", "Forum",
266
+ "Francois One", "Fredericka the Great", "Fredoka One", "Freehand", "Fresca", "Frijole", "Fugaz One", "GFS Didot",
267
+ "GFS Neohellenic", "Galdeano", "Gentium Basic", "Gentium Book Basic", "Geo", "Geostar", "Geostar Fill", "Germania One",
268
+ "Give You Glory", "Glass Antiqua", "Glegoo", "Gloria Hallelujah", "Goblin One", "Gochi Hand", "Gorditas",
269
+ "Goudy Bookletter 1911", "Graduate", "Gravitas One", "Great Vibes", "Gruppo", "Gudea", "Habibi", "Hammersmith One",
270
+ "Handlee", "Hanuman", "Happy Monkey", "Henny Penny", "Herr Von Muellerhoff", "Holtwood One SC", "Homemade Apple",
271
+ "Homenaje", "IM Fell DW Pica", "IM Fell DW Pica SC", "IM Fell Double Pica", "IM Fell Double Pica SC",
272
+ "IM Fell English", "IM Fell English SC", "IM Fell French Canon", "IM Fell French Canon SC", "IM Fell Great Primer",
273
+ "IM Fell Great Primer SC", "Iceberg", "Iceland", "Imprima", "Inconsolata", "Inder", "Indie Flower", "Inika",
274
+ "Irish Grover", "Istok Web", "Italiana", "Italianno", "Jim Nightshade", "Jockey One", "Jolly Lodger", "Josefin Sans",
275
+ "Josefin Slab", "Judson", "Julee", "Junge", "Jura", "Just Another Hand", "Just Me Again Down Here", "Kameron",
276
+ "Karla", "Kaushan Script", "Kelly Slab", "Kenia", "Khmer", "Knewave", "Kotta One", "Koulen", "Kranky", "Kreon",
277
+ "Kristi", "Krona One", "La Belle Aurore", "Lancelot", "Lato", "League Script", "Leckerli One", "Ledger", "Lekton",
278
+ "Lemon", "Lilita One", "Limelight", "Linden Hill", "Lobster", "Lobster Two", "Londrina Outline", "Londrina Shadow",
279
+ "Londrina Sketch", "Londrina Solid", "Lora", "Love Ya Like A Sister", "Loved by the King", "Lovers Quarrel",
280
+ "Luckiest Guy", "Lusitana", "Lustria", "Macondo", "Macondo Swash Caps", "Magra", "Maiden Orange", "Mako", "Marck Script",
281
+ "Marko One", "Marmelad", "Marvel", "Mate", "Mate SC", "Maven Pro", "Meddon", "MedievalSharp", "Medula One", "Merriweather",
282
+ "Metal", "Metamorphous", "Michroma", "Miltonian", "Miltonian Tattoo", "Miniver", "Miss Fajardose", "Modern Antiqua",
283
+ "Molengo", "Monofett", "Monoton", "Monsieur La Doulaise", "Montaga", "Montez", "Montserrat", "Moul", "Moulpali",
284
+ "Mountains of Christmas", "Mr Bedfort", "Mr Dafoe", "Mr De Haviland", "Mrs Saint Delafield", "Mrs Sheppards",
285
+ "Muli", "Mystery Quest", "Neucha", "Neuton", "News Cycle", "Niconne", "Nixie One", "Nobile", "Nokora", "Norican",
286
+ "Nosifer", "Nothing You Could Do", "Noticia Text", "Nova Cut", "Nova Flat", "Nova Mono", "Nova Oval", "Nova Round",
287
+ "Nova Script", "Nova Slim", "Nova Square", "Numans", "Nunito", "Odor Mean Chey", "Old Standard TT", "Oldenburg",
288
+ "Oleo Script", "Open Sans", "Open Sans Condensed", "Orbitron", "Original Surfer", "Oswald", "Over the Rainbow",
289
+ "Overlock", "Overlock SC", "Ovo", "Oxygen", "PT Mono", "PT Sans", "PT Sans Caption", "PT Sans Narrow", "PT Serif",
290
+ "PT Serif Caption", "Pacifico", "Parisienne", "Passero One", "Passion One", "Patrick Hand", "Patua One", "Paytone One",
291
+ "Permanent Marker", "Petrona", "Philosopher", "Piedra", "Pinyon Script", "Plaster", "Play", "Playball", "Playfair Display",
292
+ "Podkova", "Poiret One", "Poller One", "Poly", "Pompiere", "Pontano Sans", "Port Lligat Sans", "Port Lligat Slab",
293
+ "Prata", "Preahvihear", "Press Start 2P", "Princess Sofia", "Prociono", "Prosto One", "Puritan", "Quantico",
294
+ "Quattrocento", "Quattrocento Sans", "Questrial", "Quicksand", "Qwigley", "Radley", "Raleway", "Rammetto One",
295
+ "Rancho", "Rationale", "Redressed", "Reenie Beanie", "Revalia", "Ribeye", "Ribeye Marrow", "Righteous", "Rochester",
296
+ "Rock Salt", "Rokkitt", "Ropa Sans", "Rosario", "Rosarivo", "Rouge Script", "Ruda", "Ruge Boogie", "Ruluko",
297
+ "Ruslan Display", "Russo One", "Ruthie", "Sail", "Salsa", "Sancreek", "Sansita One", "Sarina", "Satisfy", "Schoolbell",
298
+ "Seaweed Script", "Sevillana", "Shadows Into Light", "Shadows Into Light Two", "Shanti", "Share", "Shojumaru",
299
+ "Short Stack", "Siemreap", "Sigmar One", "Signika", "Signika Negative", "Simonetta", "Sirin Stencil", "Six Caps",
300
+ "Slackey", "Smokum", "Smythe", "Sniglet", "Snippet", "Sofia", "Sonsie One", "Sorts Mill Goudy", "Special Elite",
301
+ "Spicy Rice", "Spinnaker", "Spirax", "Squada One", "Stardos Stencil", "Stint Ultra Condensed", "Stint Ultra Expanded",
302
+ "Stoke", "Sue Ellen Francisco", "Sunshiney", "Supermercado One", "Suwannaphum", "Swanky and Moo Moo", "Syncopate",
303
+ "Tangerine", "Taprom", "Telex", "Tenor Sans", "The Girl Next Door", "Tienne", "Tinos", "Titan One", "Trade Winds",
304
+ "Trocchi", "Trochut", "Trykker", "Tulpen One", "Ubuntu", "Ubuntu Condensed", "Ubuntu Mono", "Ultra", "Uncial Antiqua",
305
+ "UnifrakturCook", "UnifrakturMaguntia", "Unkempt", "Unlock", "Unna", "VT323", "Varela", "Varela Round", "Vast Shadow",
306
+ "Vibur", "Vidaloka", "Viga", "Voces", "Volkhov", "Vollkorn", "Voltaire", "Waiting for the Sunrise", "Wallpoet",
307
+ "Walter Turncoat", "Wellfleet", "Wire One", "Yanone Kaffeesatz", "Yellowtail", "Yeseva One", "Yesteryear", "Zeyada"
308
+ );
309
+ }
310
+ }
311
+ ?>
classes/filegenerator.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class to generate fiels and output them in attachment by http (https) protocol
4
+ */
5
+ class filegeneratorPps {
6
+ static protected $_instances = array();
7
+ protected $_filename = '';
8
+ protected $_data = '';
9
+ protected $_type = '';
10
+ public function __construct($filename, $data, $type) {
11
+ $this->_filename = $filename;
12
+ $this->_data = $data;
13
+ $this->_type = strtolower($type);
14
+ }
15
+ static public function getInstance($filename, $data, $type) {
16
+ $name = md5($filename. $data. $type);
17
+ if(!isset(self::$_instances[$name])) {
18
+ self::$_instances[$name] = new filegeneratorPps($filename, $data, $type);
19
+ }
20
+ return self::$_instances[$name];
21
+ }
22
+ static public function _($filename, $data, $type) {
23
+ return self::getInstance($filename, $data, $type);
24
+ }
25
+ public function generate() {
26
+ switch($this->_type) {
27
+ case 'txt':
28
+ $this->_getTxtHeader();
29
+ break;
30
+ case 'csv':
31
+ $this->_getCsvHeader();
32
+ break;
33
+ default:
34
+ $this->_getDefaultHeader();
35
+ break;
36
+ }
37
+ echo $this->_data;
38
+ exit();
39
+ }
40
+ protected function _getTxtHeader() {
41
+ header('Content-Disposition: attachment; filename="'. $this->_filename. '.txt"');
42
+ header('Content-type: text/plain');
43
+ }
44
+ protected function _getCsvHeader() {
45
+ header('Content-Disposition: attachment; filename="'. $this->_filename. '.csv"');
46
+ header('Content-type: application/csv');
47
+ }
48
+ protected function _getDefaultHeader() {
49
+ header('Content-Disposition: attachment; filename="'. $this->_filename. '"');
50
+ header('Content-type: '. $this->_type);
51
+ }
52
+ }
classes/frame.php ADDED
@@ -0,0 +1,471 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class framePps {
3
+ private $_modules = array();
4
+ private $_tables = array();
5
+ private $_allModules = array();
6
+ /**
7
+ * bool Uses to know if we are on one of the plugin pages
8
+ */
9
+ private $_inPlugin = false;
10
+ /**
11
+ * Array to hold all scripts and add them in one time in addScripts method
12
+ */
13
+ private $_scripts = array();
14
+ private $_scriptsInitialized = false;
15
+ private $_styles = array();
16
+ private $_stylesInitialized = false;
17
+ private $_useFootAssets = false;
18
+
19
+ private $_scriptsVars = array();
20
+ private $_mod = '';
21
+ private $_action = '';
22
+ /**
23
+ * Object with result of executing non-ajax module request
24
+ */
25
+ private $_res = null;
26
+
27
+ public function __construct() {
28
+ $this->_res = toeCreateObjPps('response', array());
29
+
30
+ }
31
+ static public function getInstance() {
32
+ static $instance;
33
+ if(!$instance) {
34
+ $instance = new framePps();
35
+ }
36
+ return $instance;
37
+ }
38
+ static public function _() {
39
+ return self::getInstance();
40
+ }
41
+ public function parseRoute() {
42
+ // Check plugin
43
+ $pl = reqPps::getVar('pl');
44
+ if($pl == PPS_CODE) {
45
+ $mod = reqPps::getMode();
46
+ if($mod)
47
+ $this->_mod = $mod;
48
+ $action = reqPps::getVar('action');
49
+ if($action)
50
+ $this->_action = $action;
51
+ }
52
+ }
53
+ public function setMod($mod) {
54
+ $this->_mod = $mod;
55
+ }
56
+ public function getMod() {
57
+ return $this->_mod;
58
+ }
59
+ public function setAction($action) {
60
+ $this->_action = $action;
61
+ }
62
+ public function getAction() {
63
+ return $this->_action;
64
+ }
65
+ protected function _extractModules() {
66
+ $activeModules = $this->getTable('modules')
67
+ ->innerJoin( $this->getTable('modules_type'), 'type_id' )
68
+ ->get($this->getTable('modules')->alias(). '.*, '. $this->getTable('modules_type')->alias(). '.label as type_name');
69
+ if($activeModules) {
70
+ foreach($activeModules as $m) {
71
+ $code = $m['code'];
72
+ $moduleLocationDir = PPS_MODULES_DIR;
73
+ if(!empty($m['ex_plug_dir'])) {
74
+ $moduleLocationDir = utilsPps::getExtModDir( $m['ex_plug_dir'] );
75
+ }
76
+ if(is_dir($moduleLocationDir. $code)) {
77
+ $this->_allModules[$m['code']] = 1;
78
+ if((bool)$m['active']) {
79
+ importClassPps($code. strFirstUp(PPS_CODE), $moduleLocationDir. $code. DS. 'mod.php');
80
+ $moduleClass = toeGetClassNamePps($code);
81
+ if(class_exists($moduleClass)) {
82
+ $this->_modules[$code] = new $moduleClass($m);
83
+ if(is_dir($moduleLocationDir. $code. DS. 'tables')) {
84
+ $this->_extractTables($moduleLocationDir. $code. DS. 'tables'. DS);
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ //$operationTime = microtime(true) - $startTime;
92
+ }
93
+ protected function _initModules() {
94
+ if(!empty($this->_modules)) {
95
+ foreach($this->_modules as $mod) {
96
+ $mod->init();
97
+ }
98
+ }
99
+ }
100
+ public function init() {
101
+ //$startTime = microtime(true);
102
+ reqPps::init();
103
+ $this->_extractTables();
104
+ $this->_extractModules();
105
+
106
+ $this->_initModules();
107
+
108
+ dispatcherPps::doAction('afterModulesInit');
109
+
110
+ modInstallerPps::checkActivationMessages();
111
+
112
+ $this->_execModules();
113
+
114
+ $addAssetsAction = $this->usePackAssets() && !is_admin() ? 'wp_footer' : 'init';
115
+
116
+ add_action($addAssetsAction, array($this, 'addScripts'));
117
+ add_action($addAssetsAction, array($this, 'addStyles'));
118
+
119
+ register_activation_hook( PPS_DIR. DS. PPS_MAIN_FILE, array('utilsPps', 'activatePlugin') ); //See classes/install.php file
120
+ register_uninstall_hook(PPS_DIR. DS. PPS_MAIN_FILE, array('utilsPps', 'deletePlugin'));
121
+ register_deactivation_hook(PPS_DIR. DS. PPS_MAIN_FILE, array( 'utilsPps', 'deactivatePlugin' ) );
122
+
123
+ add_action('init', array($this, 'connectLang'));
124
+ //$operationTime = microtime(true) - $startTime;
125
+ }
126
+ public function connectLang() {
127
+ load_plugin_textdomain(PPS_LANG_CODE, false, PPS_PLUG_NAME. '/lang');
128
+ }
129
+ /**
130
+ * Check permissions for action in controller by $code and made corresponding action
131
+ * @param string $code Code of controller that need to be checked
132
+ * @param string $action Action that need to be checked
133
+ * @return bool true if ok, else - should exit from application
134
+ */
135
+ public function checkPermissions($code, $action) {
136
+ if($this->havePermissions($code, $action))
137
+ return true;
138
+ else {
139
+ exit(_e('You have no permissions to view this page', PPS_LANG_CODE));
140
+ }
141
+ }
142
+ /**
143
+ * Check permissions for action in controller by $code
144
+ * @param string $code Code of controller that need to be checked
145
+ * @param string $action Action that need to be checked
146
+ * @return bool true if ok, else - false
147
+ */
148
+ public function havePermissions($code, $action) {
149
+ $res = true;
150
+ $mod = $this->getModule($code);
151
+ $action = strtolower($action);
152
+ if($mod) {
153
+ $permissions = $mod->getController()->getPermissions();
154
+ if(!empty($permissions)) { // Special permissions
155
+ if(isset($permissions[PPS_METHODS])
156
+ && !empty($permissions[PPS_METHODS])
157
+ ) {
158
+ foreach($permissions[PPS_METHODS] as $method => $permissions) { // Make case-insensitive
159
+ $permissions[PPS_METHODS][strtolower($method)] = $permissions;
160
+ }
161
+ if(array_key_exists($action, $permissions[PPS_METHODS])) { // Permission for this method exists
162
+ $currentUserPosition = framePps::_()->getModule('user')->getCurrentUserPosition();
163
+ if((is_array($permissions[ PPS_METHODS ][ $action ]) && !in_array($currentUserPosition, $permissions[ PPS_METHODS ][ $action ]))
164
+ || (!is_array($permissions[ PPS_METHODS ][ $action ]) && $permissions[PPS_METHODS][$action] != $currentUserPosition)
165
+ ) {
166
+ $res = false;
167
+ }
168
+ }
169
+ }
170
+ if(isset($permissions[PPS_USERLEVELS])
171
+ && !empty($permissions[PPS_USERLEVELS])
172
+ ) {
173
+ $currentUserPosition = framePps::_()->getModule('user')->getCurrentUserPosition();
174
+ // For multi-sites network admin role is undefined, let's do this here
175
+ if(is_multisite() && is_admin() && is_super_admin()) {
176
+ $currentUserPosition = PPS_ADMIN;
177
+ }
178
+ foreach($permissions[PPS_USERLEVELS] as $userlevel => $methods) {
179
+ if(is_array($methods)) {
180
+ $lowerMethods = array_map('strtolower', $methods); // Make case-insensitive
181
+ if(in_array($action, $lowerMethods)) { // Permission for this method exists
182
+ if($currentUserPosition != $userlevel)
183
+ $res = false;
184
+ break;
185
+ }
186
+ } else {
187
+ $lowerMethod = strtolower($methods); // Make case-insensitive
188
+ if($lowerMethod == $action) { // Permission for this method exists
189
+ if($currentUserPosition != $userlevel)
190
+ $res = false;
191
+ break;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ if($res) { // Additional check for nonces
198
+ $noncedMethods = $mod->getController()->getNoncedMethods();
199
+ if(!empty($noncedMethods)) {
200
+ $noncedMethods = array_map('strtolower', $noncedMethods);
201
+ if(in_array($action, $noncedMethods)) {
202
+ $nonce = isset($_REQUEST['_wpnonce']) ? $_REQUEST['_wpnonce'] : reqCfs::getVar('_wpnonce');
203
+ if(!wp_verify_nonce( $nonce, $action )) {
204
+ $res = false;
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ return $res;
211
+ }
212
+ public function getRes() {
213
+ return $this->_res;
214
+ }
215
+ public function execAfterWpInit() {
216
+ $this->_doExec();
217
+ }
218
+ /**
219
+ * Check if method for module require some special permission. We can detect users permissions only after wp init action was done.
220
+ */
221
+ protected function _execOnlyAfterWpInit() {
222
+ $res = false;
223
+ $mod = $this->getModule( $this->_mod );
224
+ $action = strtolower( $this->_action );
225
+ if($mod) {
226
+ $permissions = $mod->getController()->getPermissions();
227
+ if(!empty($permissions)) { // Special permissions
228
+ if(isset($permissions[PPS_METHODS])
229
+ && !empty($permissions[PPS_METHODS])
230
+ ) {
231
+ foreach($permissions[PPS_METHODS] as $method => $permissions) { // Make case-insensitive
232
+ $permissions[PPS_METHODS][strtolower($method)] = $permissions;
233
+ }
234
+ if(array_key_exists($action, $permissions[PPS_METHODS])) { // Permission for this method exists
235
+ $res = true;
236
+ }
237
+ }
238
+ if(isset($permissions[PPS_USERLEVELS])
239
+ && !empty($permissions[PPS_USERLEVELS])
240
+ ) {
241
+ $res = true;
242
+ }
243
+ }
244
+ }
245
+ return $res;
246
+ }
247
+ protected function _execModules() {
248
+ if($this->_mod) {
249
+ // If module exist and is active
250
+ $mod = $this->getModule($this->_mod);
251
+ if($mod && !empty($this->_action)) {
252
+ if($this->_execOnlyAfterWpInit()) {
253
+ add_action('init', array($this, 'execAfterWpInit'));
254
+ } else {
255
+ $this->_doExec();
256
+ }
257
+ }
258
+ }
259
+ }
260
+ protected function _doExec() {
261
+ $mod = $this->getModule($this->_mod);
262
+ if($mod && $this->checkPermissions($this->_mod, $this->_action)) {
263
+ switch(reqPps::getVar('reqType')) {
264
+ case 'ajax':
265
+ add_action('wp_ajax_'. $this->_action, array($mod->getController(), $this->_action));
266
+ add_action('wp_ajax_nopriv_'. $this->_action, array($mod->getController(), $this->_action));
267
+ break;
268
+ default:
269
+ $this->_res = $mod->exec($this->_action);
270
+ break;
271
+ }
272
+ }
273
+ }
274
+ protected function _extractTables($tablesDir = PPS_TABLES_DIR) {
275
+ $mDirHandle = opendir($tablesDir);
276
+ while(($file = readdir($mDirHandle)) !== false) {
277
+ if(is_file($tablesDir. $file) && $file != '.' && $file != '..' && strpos($file, '.php')) {
278
+ $this->_extractTable( str_replace('.php', '', $file), $tablesDir );
279
+ }
280
+ }
281
+ }
282
+ protected function _extractTable($tableName, $tablesDir = PPS_TABLES_DIR) {
283
+ importClassPps('noClassNameHere', $tablesDir. $tableName. '.php');
284
+ $this->_tables[$tableName] = tablePps::_($tableName);
285
+ }
286
+ /**
287
+ * public alias for _extractTables method
288
+ * @see _extractTables
289
+ */
290
+ public function extractTables($tablesDir) {
291
+ if(!empty($tablesDir))
292
+ $this->_extractTables($tablesDir);
293
+ }
294
+ public function exec() {
295
+ /**
296
+ * @deprecated
297
+ */
298
+ /*if(!empty($this->_modules)) {
299
+ foreach($this->_modules as $mod) {
300
+ $mod->exec();
301
+ }
302
+ }*/
303
+ }
304
+ public function getTables () {
305
+ return $this->_tables;
306
+ }
307
+ /**
308
+ * Return table by name
309
+ * @param string $tableName table name in database
310
+ * @return object table
311
+ * @example framePps::_()->getTable('products')->getAll()
312
+ */
313
+ public function getTable($tableName) {
314
+ if(empty($this->_tables[$tableName])) {
315
+ $this->_extractTable($tableName);
316
+ }
317
+ return $this->_tables[$tableName];
318
+ }
319
+ public function getModules($filter = array()) {
320
+ $res = array();
321
+ if(empty($filter))
322
+ $res = $this->_modules;
323
+ else {
324
+ foreach($this->_modules as $code => $mod) {
325
+ if(isset($filter['type'])) {
326
+ if(is_numeric($filter['type']) && $filter['type'] == $mod->getTypeID())
327
+ $res[$code] = $mod;
328
+ elseif($filter['type'] == $mod->getType())
329
+ $res[$code] = $mod;
330
+ }
331
+ }
332
+ }
333
+ return $res;
334
+ }
335
+
336
+ public function getModule($code) {
337
+ return (isset($this->_modules[$code]) ? $this->_modules[$code] : NULL);
338
+ }
339
+ public function inPlugin() {
340
+ return $this->_inPlugin;
341
+ }
342
+ public function usePackAssets() {
343
+ if(!$this->_useFootAssets && $this->getModule('options') && $this->getModule('options')->get('foot_assets')) {
344
+ $this->_useFootAssets = true;
345
+ }
346
+ return $this->_useFootAssets;
347
+ }
348
+ /**
349
+ * Push data to script array to use it all in addScripts method
350
+ * @see wp_enqueue_script definition
351
+ */
352
+ public function addScript($handle, $src = '', $deps = array(), $ver = false, $in_footer = false, $vars = array()) {
353
+ $src = empty($src) ? $src : uriPps::_($src);
354
+ if(!$ver)
355
+ $ver = PPS_VERSION;
356
+ if($this->_scriptsInitialized) {
357
+ wp_enqueue_script($handle, $src, $deps, $ver, $in_footer);
358
+ } else {
359
+ $this->_scripts[] = array(
360
+ 'handle' => $handle,
361
+ 'src' => $src,
362
+ 'deps' => $deps,
363
+ 'ver' => $ver,
364
+ 'in_footer' => $in_footer,
365
+ 'vars' => $vars
366
+ );
367
+ }
368
+ }
369
+ /**
370
+ * Add all scripts from _scripts array to worppsess
371
+ */
372
+ public function addScripts() {
373
+ if(!empty($this->_scripts)) {
374
+ foreach($this->_scripts as $s) {
375
+ wp_enqueue_script($s['handle'], $s['src'], $s['deps'], $s['ver'], $s['in_footer']);
376
+
377
+ if($s['vars'] || isset($this->_scriptsVars[$s['handle']])) {
378
+ $vars = array();
379
+ if($s['vars'])
380
+ $vars = $s['vars'];
381
+ if($this->_scriptsVars[$s['handle']])
382
+ $vars = array_merge($vars, $this->_scriptsVars[$s['handle']]);
383
+ if($vars) {
384
+ foreach($vars as $k => $v) {
385
+ wp_localize_script($s['handle'], $k, $v);
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+ $this->_scriptsInitialized = true;
392
+ }
393
+ public function addJSVar($script, $name, $val) {
394
+ if($this->_scriptsInitialized) {
395
+ wp_localize_script($script, $name, $val);
396
+ } else {
397
+ $this->_scriptsVars[$script][$name] = $val;
398
+ }
399
+ }
400
+
401
+ public function addStyle($handle, $src = false, $deps = array(), $ver = false, $media = 'all') {
402
+ $src = empty($src) ? $src : uriPps::_($src);
403
+ if(!$ver)
404
+ $ver = PPS_VERSION;
405
+ if($this->_stylesInitialized) {
406
+ wp_enqueue_style($handle, $src, $deps, $ver, $media);
407
+ } else {
408
+ $this->_styles[] = array(
409
+ 'handle' => $handle,
410
+ 'src' => $src,
411
+ 'deps' => $deps,
412
+ 'ver' => $ver,
413
+ 'media' => $media
414
+ );
415
+ }
416
+ }
417
+ public function addStyles() {
418
+ if(!empty($this->_styles)) {
419
+ foreach($this->_styles as $s) {
420
+ wp_enqueue_style($s['handle'], $s['src'], $s['deps'], $s['ver'], $s['media']);
421
+ }
422
+ }
423
+ $this->_stylesInitialized = true;
424
+ }
425
+ //Very interesting thing going here.............
426
+ public function loadPlugins() {
427
+ require_once(ABSPATH. 'wp-includes/pluggable.php');
428
+ }
429
+ public function loadWPSettings() {
430
+ require_once(ABSPATH. 'wp-settings.php');
431
+ }
432
+ public function loadLocale() {
433
+ require_once(ABSPATH. 'wp-includes/locale.php');
434
+ }
435
+ public function moduleActive($code) {
436
+ return isset($this->_modules[$code]);
437
+ }
438
+ public function moduleExists($code) {
439
+ if($this->moduleActive($code))
440
+ return true;
441
+ return isset($this->_allModules[$code]);
442
+ }
443
+ public function isTplEditor() {
444
+ $tplEditor = reqPps::getVar('tplEditor');
445
+ return (bool) $tplEditor;
446
+ }
447
+ /**
448
+ * This is custom method for each plugin and should be modified if you create copy from this instance.
449
+ */
450
+ public function isAdminPlugOptsPage() {
451
+ $page = reqPps::getVar('page');
452
+ if(is_admin() && strpos($page, framePps::_()->getModule('adminmenu')->getMainSlug()) !== false)
453
+ return true;
454
+ return false;
455
+ }
456
+ public function isAdminPlugPage() {
457
+ if($this->isAdminPlugOptsPage()) {
458
+ return true;
459
+ }
460
+ return false;
461
+ }
462
+ public function licenseDeactivated() {
463
+ return (!$this->getModule('license') && $this->moduleExists('license'));
464
+ }
465
+ public function savePluginActivationErrors() {
466
+ update_option(PPS_CODE. '_plugin_activation_errors', ob_get_contents());
467
+ }
468
+ public function getActivationErrors() {
469
+ return get_option(PPS_CODE. '_plugin_activation_errors');
470
+ }
471
+ }
classes/helper.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Abstract class of module helper
4
+ * Module helper has all the functions that are needed in module workflow
5
+ * Besides it contains the methods to build html elements
6
+ */
7
+ abstract class helperPps {
8
+ protected $_code = '';
9
+ protected $_module = '';
10
+ /**
11
+ * Construct helper class
12
+ * @param string $code
13
+ */
14
+ public function __construct($code) {
15
+ $this->setCode($code);
16
+ }
17
+ /**
18
+ * Init function
19
+ */
20
+ public function init(){
21
+
22
+ }
23
+ /**
24
+ * Set the helper name
25
+ * @param string $code
26
+ */
27
+ public function setCode($code) {
28
+ $this->_code = $code;
29
+ }
30
+ /**
31
+ * Get the helper name
32
+ * @return string
33
+ */
34
+ public function getCode() {
35
+ return $this->_code;
36
+ }
37
+ }
38
+
classes/helpers/SxGeo.php ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /***************************************************************************\
3
+ | Sypex Geo version 2.2.3 |
4
+ | (c)2006-2014 zapimir zapimir@zapimir.net http://sypex.net/ |
5
+ | (c)2006-2014 BINOVATOR info@sypex.net |
6
+ |---------------------------------------------------------------------------|
7
+ | created: 2006.10.17 18:33 modified: 2014.06.20 18:57 |
8
+ |---------------------------------------------------------------------------|
9
+ | Sypex Geo is released under the terms of the BSD license |
10
+ | http://sypex.net/bsd_license.txt |
11
+ \***************************************************************************/
12
+
13
+ define ('SXGEO_FILE', 0);
14
+ define ('SXGEO_MEMORY', 1);
15
+ define ('SXGEO_BATCH', 2);
16
+ class SxGeo {
17
+ protected $fh;
18
+ protected $ip1c;
19
+ protected $info;
20
+ protected $range;
21
+ protected $db_begin;
22
+ protected $b_idx_str;
23
+ protected $m_idx_str;
24
+ protected $b_idx_arr;
25
+ protected $m_idx_arr;
26
+ protected $m_idx_len;
27
+ protected $db_items;
28
+ protected $country_size;
29
+ protected $db;
30
+ protected $regions_db;
31
+ protected $cities_db;
32
+
33
+ public $id2iso = array(
34
+ '', 'AP', 'EU', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'CW', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU',
35
+ 'AW', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BM', 'BN', 'BO', 'BR', 'BS',
36
+ 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN',
37
+ 'CO', 'CR', 'CU', 'CV', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG',
38
+ 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'SX', 'GA', 'GB', 'GD', 'GE', 'GF',
39
+ 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN',
40
+ 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JM', 'JO', 'JP', 'KE',
41
+ 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR',
42
+ 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP',
43
+ 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI',
44
+ 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN',
45
+ 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG',
46
+ 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'ST', 'SV', 'SY', 'SZ', 'TC', 'TD', 'TF',
47
+ 'TG', 'TH', 'TJ', 'TK', 'TM', 'TN', 'TO', 'TL', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM',
48
+ 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'RS', 'ZA',
49
+ 'ZM', 'ME', 'ZW', 'A1', 'XK', 'O1', 'AX', 'GG', 'IM', 'JE', 'BL', 'MF', 'BQ', 'SS'
50
+ );
51
+
52
+ public $batch_mode = false;
53
+ public $memory_mode = false;
54
+
55
+ public function __construct($db_file = 'SxGeo.dat', $type = SXGEO_FILE){
56
+ $this->fh = fopen($db_file, 'rb');
57
+ // Сначала убеждаемся, что есть файл базы данных
58
+ $header = fread($this->fh, 40); // В версии 2.2 заголовок увеличился на 8 байт
59
+ if(substr($header, 0, 3) != 'SxG') die("Can't open {$db_file}\n");
60
+ $info = unpack('Cver/Ntime/Ctype/Ccharset/Cb_idx_len/nm_idx_len/nrange/Ndb_items/Cid_len/nmax_region/nmax_city/Nregion_size/Ncity_size/nmax_country/Ncountry_size/npack_size', substr($header, 3));
61
+ if($info['b_idx_len'] * $info['m_idx_len'] * $info['range'] * $info['db_items'] * $info['time'] * $info['id_len'] == 0) die("Wrong file format {$db_file}\n");
62
+ $this->range = $info['range'];
63
+ $this->b_idx_len = $info['b_idx_len'];
64
+ $this->m_idx_len = $info['m_idx_len'];
65
+ $this->db_items = $info['db_items'];
66
+ $this->id_len = $info['id_len'];
67
+ $this->block_len = 3 + $this->id_len;
68
+ $this->max_region = $info['max_region'];
69
+ $this->max_city = $info['max_city'];
70
+ $this->max_country = $info['max_country'];
71
+ $this->country_size= $info['country_size'];
72
+ $this->batch_mode = $type & SXGEO_BATCH;
73
+ $this->memory_mode = $type & SXGEO_MEMORY;
74
+ $this->pack = $info['pack_size'] ? explode("\0", fread($this->fh, $info['pack_size'])) : '';
75
+ $this->b_idx_str = fread($this->fh, $info['b_idx_len'] * 4);
76
+ $this->m_idx_str = fread($this->fh, $info['m_idx_len'] * 4);
77
+
78
+ $this->db_begin = ftell($this->fh);
79
+ if ($this->batch_mode) {
80
+ $this->b_idx_arr = array_values(unpack("N*", $this->b_idx_str)); // Быстрее в 5 раз, чем с циклом
81
+ unset ($this->b_idx_str);
82
+ $this->m_idx_arr = str_split($this->m_idx_str, 4); // Быстрее в 5 раз чем с циклом
83
+ unset ($this->m_idx_str);
84
+ }
85
+ if ($this->memory_mode) {
86
+ $this->db = fread($this->fh, $this->db_items * $this->block_len);
87
+ $this->regions_db = $info['region_size'] > 0 ? fread($this->fh, $info['region_size']) : '';
88
+ $this->cities_db = $info['city_size'] > 0 ? fread($this->fh, $info['city_size']) : '';
89
+ }
90
+ $this->info = $info;
91
+ $this->info['regions_begin'] = $this->db_begin + $this->db_items * $this->block_len;
92
+ $this->info['cities_begin'] = $this->info['regions_begin'] + $info['region_size'];
93
+ }
94
+
95
+ protected function search_idx($ipn, $min, $max){
96
+ if($this->batch_mode){
97
+ while($max - $min > 8){
98
+ $offset = ($min + $max) >> 1;
99
+ if ($ipn > $this->m_idx_arr[$offset]) $min = $offset;
100
+ else $max = $offset;
101
+ }
102
+ while ($ipn > $this->m_idx_arr[$min] && $min++ < $max){};
103
+ }
104
+ else {
105
+ while($max - $min > 8){
106
+ $offset = ($min + $max) >> 1;
107
+ if ($ipn > substr($this->m_idx_str, $offset*4, 4)) $min = $offset;
108
+ else $max = $offset;
109
+ }
110
+ while ($ipn > substr($this->m_idx_str, $min*4, 4) && $min++ < $max){};
111
+ }
112
+ return $min;
113
+ }
114
+
115
+ protected function search_db($str, $ipn, $min, $max){
116
+ if($max - $min > 1) {
117
+ $ipn = substr($ipn, 1);
118
+ while($max - $min > 8){
119
+ $offset = ($min + $max) >> 1;
120
+ if ($ipn > substr($str, $offset * $this->block_len, 3)) $min = $offset;
121
+ else $max = $offset;
122
+ }
123
+ while ($ipn >= substr($str, $min * $this->block_len, 3) && ++$min < $max){};
124
+ }
125
+ else {
126
+ $min++;
127
+ }
128
+ return hexdec(bin2hex(substr($str, $min * $this->block_len - $this->id_len, $this->id_len)));
129
+ }
130
+
131
+ public function get_num($ip){
132
+ $ip1n = (int)$ip; // Первый байт
133
+ if($ip1n == 0 || $ip1n == 10 || $ip1n == 127 || $ip1n >= $this->b_idx_len || false === ($ipn = ip2long($ip))) return false;
134
+ $ipn = pack('N', $ipn);
135
+ $this->ip1c = chr($ip1n);
136
+ // Находим блок данных в индексе первых байт
137
+ if ($this->batch_mode){
138
+ $blocks = array('min' => $this->b_idx_arr[$ip1n-1], 'max' => $this->b_idx_arr[$ip1n]);
139
+ }
140
+ else {
141
+ $blocks = unpack("Nmin/Nmax", substr($this->b_idx_str, ($ip1n - 1) * 4, 8));
142
+ }
143
+ if ($blocks['max'] - $blocks['min'] > $this->range){
144
+ // Ищем блок в основном индексе
145
+ $part = $this->search_idx($ipn, floor($blocks['min'] / $this->range), floor($blocks['max'] / $this->range)-1);
146
+ // Нашли номер блока в котором нужно искать IP, теперь находим нужный блок в БД
147
+ $min = $part > 0 ? $part * $this->range : 0;
148
+ $max = $part > $this->m_idx_len ? $this->db_items : ($part+1) * $this->range;
149
+ // Нужно проверить чтобы блок не выходил за пределы блока первого байта
150
+ if($min < $blocks['min']) $min = $blocks['min'];
151
+ if($max > $blocks['max']) $max = $blocks['max'];
152
+ }
153
+ else {
154
+ $min = $blocks['min'];
155
+ $max = $blocks['max'];
156
+ }
157
+ $len = $max - $min;
158
+ // Находим нужный диапазон в БД
159
+ if ($this->memory_mode) {
160
+ return $this->search_db($this->db, $ipn, $min, $max);
161
+ }
162
+ else {
163
+ fseek($this->fh, $this->db_begin + $min * $this->block_len);
164
+ return $this->search_db(fread($this->fh, $len * $this->block_len), $ipn, 0, $len);
165
+ }
166
+ }
167
+
168
+ protected function readData($seek, $max, $type){
169
+ $raw = '';
170
+ if($seek && $max) {
171
+ if ($this->memory_mode) {
172
+ $raw = substr($type == 1 ? $this->regions_db : $this->cities_db, $seek, $max);
173
+ } else {
174
+ fseek($this->fh, $this->info[$type == 1 ? 'regions_begin' : 'cities_begin'] + $seek);
175
+ $raw = fread($this->fh, $max);
176
+ }
177
+ }
178
+ return $this->unpack($this->pack[$type], $raw);
179
+ }
180
+
181
+ protected function parseCity($seek, $full = false){
182
+ if(!$this->pack) return false;
183
+ $only_country = false;
184
+ if($seek < $this->country_size){
185
+ $country = $this->readData($seek, $this->max_country, 0);
186
+ $city = $this->unpack($this->pack[2]);
187
+ $city['lat'] = $country['lat'];
188
+ $city['lon'] = $country['lon'];
189
+ $only_country = true;
190
+ }
191
+ else {
192
+ $city = $this->readData($seek, $this->max_city, 2);
193
+ $country = array('id' => $city['country_id'], 'iso' => $this->id2iso[$city['country_id']]);
194
+ unset($city['country_id']);
195
+ }
196
+ if($full) {
197
+ $region = $this->readData($city['region_seek'], $this->max_region, 1);
198
+ if(!$only_country) $country = $this->readData($region['country_seek'], $this->max_country, 0);
199
+ unset($city['region_seek']);
200
+ unset($region['country_seek']);
201
+ return array('city' => $city, 'region' => $region, 'country' => $country);
202
+ }
203
+ else {
204
+ unset($city['region_seek']);
205
+ return array('city' => $city, 'country' => array('id' => $country['id'], 'iso' => $country['iso']));
206
+ }
207
+ }
208
+
209
+ protected function unpack($pack, $item = ''){
210
+ $unpacked = array();
211
+ $empty = empty($item);
212
+ $pack = explode('/', $pack);
213
+ $pos = 0;
214
+ foreach($pack AS $p){
215
+ list($type, $name) = explode(':', $p);
216
+ $type0 = $type{0};
217
+ if($empty) {
218
+ $unpacked[$name] = $type0 == 'b' || $type0 == 'c' ? '' : 0;
219
+ continue;
220
+ }
221
+ switch($type0){
222
+ case 't':
223
+ case 'T': $l = 1; break;
224
+ case 's':
225
+ case 'n':
226
+ case 'S': $l = 2; break;
227
+ case 'm':
228
+ case 'M': $l = 3; break;
229
+ case 'd': $l = 8; break;
230
+ case 'c': $l = (int)substr($type, 1); break;
231
+ case 'b': $l = strpos($item, "\0", $pos)-$pos; break;
232
+ default: $l = 4;
233
+ }
234
+ $val = substr($item, $pos, $l);
235
+ switch($type0){
236
+ case 't': $v = unpack('c', $val); break;
237
+ case 'T': $v = unpack('C', $val); break;
238
+ case 's': $v = unpack('s', $val); break;
239
+ case 'S': $v = unpack('S', $val); break;
240
+ case 'm': $v = unpack('l', $val . (ord($val{2}) >> 7 ? "\xff" : "\0")); break;
241
+ case 'M': $v = unpack('L', $val . "\0"); break;
242
+ case 'i': $v = unpack('l', $val); break;
243
+ case 'I': $v = unpack('L', $val); break;
244
+ case 'f': $v = unpack('f', $val); break;
245
+ case 'd': $v = unpack('d', $val); break;
246
+
247
+ case 'n': $v = current(unpack('s', $val)) / pow(10, $type{1}); break;
248
+ case 'N': $v = current(unpack('l', $val)) / pow(10, $type{1}); break;
249
+
250
+ case 'c': $v = rtrim($val, ' '); break;
251
+ case 'b': $v = $val; $l++; break;
252
+ }
253
+ $pos += $l;
254
+ $unpacked[$name] = is_array($v) ? current($v) : $v;
255
+ }
256
+ return $unpacked;
257
+ }
258
+
259
+ public function get($ip){
260
+ return $this->max_city ? $this->getCity($ip) : $this->getCountry($ip);
261
+ }
262
+ public function getCountry($ip){
263
+ if($this->max_city) {
264
+ $tmp = $this->parseCity($this->get_num($ip));
265
+ return $tmp['country']['iso'];
266
+ }
267
+ else return $this->id2iso[$this->get_num($ip)];
268
+ }
269
+ public function getCountryId($ip){
270
+ if($this->max_city) {
271
+ $tmp = $this->parseCity($this->get_num($ip));
272
+ return $tmp['country']['id'];
273
+ }
274
+ else return $this->get_num($ip);
275
+ }
276
+ public function getCity($ip){
277
+ $seek = $this->get_num($ip);
278
+ return $seek ? $this->parseCity($seek) : false;
279
+ }
280
+ public function getCityFull($ip){
281
+ $seek = $this->get_num($ip);
282
+ return $seek ? $this->parseCity($seek, 1) : false;
283
+ }
284
+ public function about(){
285
+ $charset = array('utf-8', 'latin1', 'cp1251');
286
+ $types = array('n/a', 'SxGeo Country', 'SxGeo City RU', 'SxGeo City EN', 'SxGeo City', 'SxGeo City Max RU', 'SxGeo City Max EN', 'SxGeo City Max');
287
+ return array(
288
+ 'Created' => date('Y.m.d', $this->info['time']),
289
+ 'Timestamp' => $this->info['time'],
290
+ 'Charset' => $charset[$this->info['charset']],
291
+ 'Type' => $types[$this->info['type']],
292
+ 'Byte Index' => $this->b_idx_len,
293
+ 'Main Index' => $this->m_idx_len,
294
+ 'Blocks In Index Item' => $this->range,
295
+ 'IP Blocks' => $this->db_items,
296
+ 'Block Size' => $this->block_len,
297
+ 'City' => array(
298
+ 'Max Length' => $this->max_city,
299
+ 'Total Size' => $this->info['city_size'],
300
+ ),
301
+ 'Region' => array(
302
+ 'Max Length' => $this->max_region,
303
+ 'Total Size' => $this->info['region_size'],
304
+ ),
305
+ 'Country' => array(
306
+ 'Max Length' => $this->max_country,
307
+ 'Total Size' => $this->info['country_size'],
308
+ ),
309
+ );
310
+ }
311
+ }
classes/helpers/mobileDetect.php ADDED
@@ -0,0 +1,1458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mobile Detect Library
4
+ * =====================
5
+ *
6
+ * Motto: "Every business should have a mobile detection script to detect mobile readers"
7
+ *
8
+ * Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets).
9
+ * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
10
+ *
11
+ * @author Current authors: Serban Ghita <serbanghita@gmail.com>
12
+ * Nick Ilyin <nick.ilyin@gmail.com>
13
+ *
14
+ * Original author: Victor Stanciu <vic.stanciu@gmail.com>
15
+ *
16
+ * @license Code and contributions have 'MIT License'
17
+ * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
18
+ *
19
+ * @link Homepage: http://mobiledetect.net
20
+ * GitHub Repo: https://github.com/serbanghita/Mobile-Detect
21
+ * Google Code: http://code.google.com/p/php-mobile-detect/
22
+ * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
23
+ * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
24
+ *
25
+ * @version 2.8.24
26
+ */
27
+
28
+ class Mobile_Detect
29
+ {
30
+ /**
31
+ * Mobile detection type.
32
+ *
33
+ * @deprecated since version 2.6.9
34
+ */
35
+ const DETECTION_TYPE_MOBILE = 'mobile';
36
+
37
+ /**
38
+ * Extended detection type.
39
+ *
40
+ * @deprecated since version 2.6.9
41
+ */
42
+ const DETECTION_TYPE_EXTENDED = 'extended';
43
+
44
+ /**
45
+ * A frequently used regular expression to extract version #s.
46
+ *
47
+ * @deprecated since version 2.6.9
48
+ */
49
+ const VER = '([\w._\+]+)';
50
+
51
+ /**
52
+ * Top-level device.
53
+ */
54
+ const MOBILE_GRADE_A = 'A';
55
+
56
+ /**
57
+ * Mid-level device.
58
+ */
59
+ const MOBILE_GRADE_B = 'B';
60
+
61
+ /**
62
+ * Low-level device.
63
+ */
64
+ const MOBILE_GRADE_C = 'C';
65
+
66
+ /**
67
+ * Stores the version number of the current release.
68
+ */
69
+ const VERSION = '2.8.24';
70
+
71
+ /**
72
+ * A type for the version() method indicating a string return value.
73
+ */
74
+ const VERSION_TYPE_STRING = 'text';
75
+
76
+ /**
77
+ * A type for the version() method indicating a float return value.
78
+ */
79
+ const VERSION_TYPE_FLOAT = 'float';
80
+
81
+ /**
82
+ * A cache for resolved matches
83
+ * @var array
84
+ */
85
+ protected $cache = array();
86
+
87
+ /**
88
+ * The User-Agent HTTP header is stored in here.
89
+ * @var string
90
+ */
91
+ protected $userAgent = null;
92
+
93
+ /**
94
+ * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
95
+ * @var array
96
+ */
97
+ protected $httpHeaders = array();
98
+
99
+ /**
100
+ * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer.
101
+ * @var array
102
+ */
103
+ protected $cloudfrontHeaders = array();
104
+
105
+ /**
106
+ * The matching Regex.
107
+ * This is good for debug.
108
+ * @var string
109
+ */
110
+ protected $matchingRegex = null;
111
+
112
+ /**
113
+ * The matches extracted from the regex expression.
114
+ * This is good for debug.
115
+ * @var string
116
+ */
117
+ protected $matchesArray = null;
118
+
119
+ /**
120
+ * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
121
+ *
122
+ * @deprecated since version 2.6.9
123
+ *
124
+ * @var string
125
+ */
126
+ protected $detectionType = self::DETECTION_TYPE_MOBILE;
127
+
128
+ /**
129
+ * HTTP headers that trigger the 'isMobile' detection
130
+ * to be true.
131
+ *
132
+ * @var array
133
+ */
134
+ protected static $mobileHeaders = array(
135
+
136
+ 'HTTP_ACCEPT' => array('matches' => array(
137
+ // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
138
+ 'application/x-obml2d',
139
+ // BlackBerry devices.
140
+ 'application/vnd.rim.html',
141
+ 'text/vnd.wap.wml',
142
+ 'application/vnd.wap.xhtml+xml'
143
+ )),
144
+ 'HTTP_X_WAP_PROFILE' => null,
145
+ 'HTTP_X_WAP_CLIENTID' => null,
146
+ 'HTTP_WAP_CONNECTION' => null,
147
+ 'HTTP_PROFILE' => null,
148
+ // Reported by Opera on Nokia devices (eg. C3).
149
+ 'HTTP_X_OPERAMINI_PHONE_UA' => null,
150
+ 'HTTP_X_NOKIA_GATEWAY_ID' => null,
151
+ 'HTTP_X_ORANGE_ID' => null,
152
+ 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
153
+ 'HTTP_X_HUAWEI_USERID' => null,
154
+ // Reported by Windows Smartphones.
155
+ 'HTTP_UA_OS' => null,
156
+ // Reported by Verizon, Vodafone proxy system.
157
+ 'HTTP_X_MOBILE_GATEWAY' => null,
158
+ // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
159
+ 'HTTP_X_ATT_DEVICEID' => null,
160
+ // Seen this on a HTC.
161
+ 'HTTP_UA_CPU' => array('matches' => array('ARM')),
162
+ );
163
+
164
+ /**
165
+ * List of mobile devices (phones).
166
+ *
167
+ * @var array
168
+ */
169
+ protected static $phoneDevices = array(
170
+ 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
171
+ 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
172
+ 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m',
173
+ 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
174
+ // @todo: Is 'Dell Streak' a tablet or a phone? ;)
175
+ 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
176
+ 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b',
177
+ 'Samsung' => '\bSamsung\b|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F',
178
+ 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)',
179
+ 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
180
+ 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
181
+ 'NokiaLumia' => 'Lumia [0-9]{3,4}',
182
+ // http://www.micromaxinfo.com/mobiles/smartphones
183
+ // Added because the codes might conflict with Acer Tablets.
184
+ 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
185
+ // @todo Complete the regex.
186
+ 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
187
+ 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
188
+ // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
189
+ // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
190
+ 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
191
+ // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
192
+ 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
193
+ // http://fr.wikomobile.com
194
+ 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM',
195
+ 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
196
+ // Added simvalley mobile just for fun. They have some interesting devices.
197
+ // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
198
+ 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
199
+ // Wolfgang - a brand that is sold by Aldi supermarkets.
200
+ // http://www.wolfgangmobile.com/
201
+ 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
202
+ 'Alcatel' => 'Alcatel',
203
+ 'Nintendo' => 'Nintendo 3DS',
204
+ // http://en.wikipedia.org/wiki/Amoi
205
+ 'Amoi' => 'Amoi',
206
+ // http://en.wikipedia.org/wiki/INQ
207
+ 'INQ' => 'INQ',
208
+ // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
209
+ 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser',
210
+ );
211
+
212
+ /**
213
+ * List of tablet devices.
214
+ *
215
+ * @var array
216
+ */
217
+ protected static $tabletDevices = array(
218
+ // @todo: check for mobile friendly emails topic.
219
+ 'iPad' => 'iPad|iPad.*Mobile',
220
+ // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
221
+ // @see #442
222
+ 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
223
+ 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
224
+ // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
225
+ 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI)\b',
226
+ // Only the Surface tablets with Windows RT are considered mobile.
227
+ // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
228
+ 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
229
+ // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
230
+ 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
231
+ // Watch out for PadFone, see #132.
232
+ // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
233
+ 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z',
234
+ 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
235
+ 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
236
+ 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
237
+ 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
238
+ // http://www.acer.ro/ac/ro/RO/content/drivers
239
+ // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
240
+ // http://us.acer.com/ac/en/US/content/group/tablets
241
+ // http://www.acer.de/ac/de/DE/content/models/tablets/
242
+ // Can conflict with Micromax and Motorola phones codes.
243
+ 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30',
244
+ // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
245
+ // http://us.toshiba.com/tablets/tablet-finder
246
+ // http://www.toshiba.co.jp/regza/tablet/
247
+ 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
248
+ // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
249
+ // http://www.lg.com/us/tablets
250
+ 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
251
+ 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
252
+ // Prestigio Tablets http://www.prestigio.com/support
253
+ 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
254
+ // http://support.lenovo.com/en_GB/downloads/default.page?#
255
+ 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)',
256
+ // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
257
+ 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
258
+ // http://www.yarvik.com/en/matrix/tablets/
259
+ 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
260
+ 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
261
+ 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
262
+ // http://www.intenso.de/kategorie_en.php?kategorie=33
263
+ // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
264
+ 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
265
+ // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
266
+ 'IRUTablet' => 'M702pro',
267
+ 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
268
+ // http://www.e-boda.ro/tablete-pc.html
269
+ 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
270
+ // http://www.allview.ro/produse/droseries/lista-tablete-pc/
271
+ 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
272
+ // http://wiki.archosfans.com/index.php?title=Main_Page
273
+ 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
274
+ // http://www.ainol.com/plugin.php?identifier=ainol&module=product
275
+ 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
276
+ 'NokiaLumiaTablet' => 'Lumia 2520',
277
+ // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
278
+ // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
279
+ // http://www.sony.jp/support/tablet/
280
+ 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31',
281
+ // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8
282
+ 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
283
+ // db + http://www.cube-tablet.com/buy-products.html
284
+ 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
285
+ // http://www.cobyusa.com/?p=pcat&pcat_id=3001
286
+ 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
287
+ // http://www.match.net.cn/products.asp
288
+ 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
289
+ // http://www.msi.com/support
290
+ // @todo Research the Windows Tablets.
291
+ 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
292
+ // @todo http://www.kyoceramobile.com/support/drivers/
293
+ // 'KyoceraTablet' => null,
294
+ // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
295
+ // 'IntextTablet' => null,
296
+ // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
297
+ // http://www.imp3.net/14/show.php?itemid=20454
298
+ 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
299
+ // http://www.rock-chips.com/index.php?do=prod&pid=2
300
+ 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
301
+ // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
302
+ 'FlyTablet' => 'IQ310|Fly Vision',
303
+ // http://www.bqreaders.com/gb/tablets-prices-sale.html
304
+ 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris [E|M]10)|Maxwell.*Lite|Maxwell.*Plus',
305
+ // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
306
+ // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
307
+ 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
308
+ // Nec or Medias Tab
309
+ 'NecTablet' => '\bN-06D|\bN-08D',
310
+ // Pantech Tablets: http://www.pantechusa.com/phones/
311
+ 'PantechTablet' => 'Pantech.*P4100',
312
+ // Broncho Tablets: http://www.broncho.cn/ (hard to find)
313
+ 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
314
+ // http://versusuk.com/support.html
315
+ 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
316
+ // http://www.zync.in/index.php/our-products/tablet-phablets
317
+ 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
318
+ // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
319
+ 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
320
+ // https://www.nabitablet.com/
321
+ 'NabiTablet' => 'Android.*\bNabi',
322
+ 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
323
+ // French Danew Tablets http://www.danew.com/produits-tablette.php
324
+ 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
325
+ // Texet Tablets and Readers http://www.texet.ru/tablet/
326
+ 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
327
+ // Avoid detecting 'PLAYSTATION 3' as mobile.
328
+ 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
329
+ // http://www.trekstor.de/surftabs.html
330
+ 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
331
+ // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
332
+ 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
333
+ // http://www.advandigital.com/index.php?link=content-product&jns=JP001
334
+ // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
335
+ 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
336
+ // http://www.danytech.com/category/tablet-pc
337
+ 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
338
+ // http://www.galapad.net/product.html
339
+ 'GalapadTablet' => 'Android.*\bG1\b',
340
+ // http://www.micromaxinfo.com/tablet/funbook
341
+ 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
342
+ // http://www.karbonnmobiles.com/products_tablet.php
343
+ 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
344
+ // http://www.myallfine.com/Products.asp
345
+ 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
346
+ // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
347
+ 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
348
+ // http://www.yonesnav.com/products/products.php
349
+ 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
350
+ // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
351
+ // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
352
+ 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
353
+ // http://www.gloryunion.cn/products.asp
354
+ // http://www.allwinnertech.com/en/apply/mobile.html
355
+ // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
356
+ // @todo: Softwiner tablets?
357
+ // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
358
+ 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
359
+ // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
360
+ 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
361
+ // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
362
+ // @todo: add more tests.
363
+ 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
364
+ // http://hclmetablet.com/India/index.php
365
+ 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
366
+ // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
367
+ 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
368
+ // http://www.visture.com/index.asp
369
+ 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
370
+ // http://www.mijncresta.nl/tablet
371
+ 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
372
+ // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
373
+ 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
374
+ // Concorde tab
375
+ 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
376
+ // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
377
+ 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
378
+ // Modecom Tablets - http://www.modecom.eu/tablets/portal/
379
+ 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
380
+ // Vonino Tablets - http://www.vonino.eu/tablets
381
+ 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
382
+ // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
383
+ 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
384
+ // Storex Tablets - http://storex.fr/espace_client/support.html
385
+ // @note: no need to add all the tablet codes since they are guided by the first regex.
386
+ 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
387
+ // Generic Vodafone tablets.
388
+ 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497',
389
+ // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
390
+ // Aka: http://www.essentielb.fr/
391
+ 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
392
+ // Ross & Moor - http://ross-moor.ru/
393
+ 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
394
+ // i-mobile http://product.i-mobilephone.com/Mobile_Device
395
+ 'iMobileTablet' => 'i-mobile i-note',
396
+ // http://www.tolino.de/de/vergleichen/
397
+ 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
398
+ // AudioSonic - a Kmart brand
399
+ // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72&currentPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
400
+ 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
401
+ // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
402
+ // @todo: add them gradually to avoid conflicts.
403
+ 'AMPETablet' => 'Android.* A78 ',
404
+ // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
405
+ 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
406
+ // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
407
+ 'TecnoTablet' => 'TECNO P9',
408
+ // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
409
+ 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
410
+ // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
411
+ 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
412
+ // http://www.intracon.eu/tablet
413
+ 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
414
+ // http://www.xoro.de/produkte/
415
+ // @note: Might be the same brand with 'Simply tablets'
416
+ 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
417
+ // http://www1.viewsonic.com/products/computing/tablets/
418
+ 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
419
+ // http://www.odys.de/web/internet-tablet_en.html
420
+ 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
421
+ // http://www.captiva-power.de/products.html#tablets-en
422
+ 'CaptivaTablet' => 'CAPTIVA PAD',
423
+ // IconBIT - http://www.iconbit.com/products/tablets/
424
+ 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
425
+ // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
426
+ 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
427
+ // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price
428
+ 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+',
429
+ 'JaytechTablet' => 'TPC-PA762',
430
+ 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
431
+ // http://www.digma.ru/support/download/
432
+ // @todo: Ebooks also (if requested)
433
+ 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
434
+ // http://www.evolioshop.com/ro/tablete-pc.html
435
+ // http://www.evolio.ro/support/downloads_static.html?cat=2
436
+ // @todo: Research some more
437
+ 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
438
+ // @todo http://www.lavamobiles.com/tablets-data-cards
439
+ 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
440
+ // http://www.breezetablet.com/
441
+ 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
442
+ // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/
443
+ 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
444
+ // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
445
+ 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
446
+ // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab
447
+ 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
448
+ // http://www.mi.com/en
449
+ 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
450
+ // http://www.nbru.cn/index.html
451
+ 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
452
+ // http://navroad.com/products/produkty/tablety/
453
+ 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
454
+ // http://leader-online.com/new_site/product-category/tablets/
455
+ // http://www.leader-online.net.au/List/Tablet
456
+ 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
457
+ // http://www.datawind.com/ubislate/
458
+ 'UbislateTablet' => 'UbiSlate[\s]?7C',
459
+ // http://www.pocketbook-int.com/ru/support
460
+ 'PocketBookTablet' => 'Pocketbook',
461
+ // http://www.kocaso.com/product_tablet.html
462
+ 'KocasoTablet' => '\b(TB-1207)\b',
463
+ // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm
464
+ 'HisenseTablet' => '\b(F5281|E2371)\b',
465
+ // http://www.tesco.com/direct/hudl/
466
+ 'Hudl' => 'Hudl HT7S3|Hudl 2',
467
+ // http://www.telstra.com.au/home-phone/thub-2/
468
+ 'TelstraTablet' => 'T-Hub2',
469
+ 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b'
470
+ );
471
+
472
+ /**
473
+ * List of mobile Operating Systems.
474
+ *
475
+ * @var array
476
+ */
477
+ protected static $operatingSystems = array(
478
+ 'AndroidOS' => 'Android',
479
+ 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
480
+ 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
481
+ 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
482
+ // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
483
+ 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
484
+ // @reference: http://en.wikipedia.org/wiki/Windows_Phone
485
+ // http://wifeng.cn/?r=blog&a=view&id=106
486
+ // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
487
+ // http://msdn.microsoft.com/library/ms537503.aspx
488
+ // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
489
+ 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
490
+ 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
491
+ // http://en.wikipedia.org/wiki/MeeGo
492
+ // @todo: research MeeGo in UAs
493
+ 'MeeGoOS' => 'MeeGo',
494
+ // http://en.wikipedia.org/wiki/Maemo
495
+ // @todo: research Maemo in UAs
496
+ 'MaemoOS' => 'Maemo',
497
+ 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
498
+ 'webOS' => 'webOS|hpwOS',
499
+ 'badaOS' => '\bBada\b',
500
+ 'BREWOS' => 'BREW',
501
+ );
502
+
503
+ /**
504
+ * List of mobile User Agents.
505
+ *
506
+ * IMPORTANT: This is a list of only mobile browsers.
507
+ * Mobile Detect 2.x supports only mobile browsers,
508
+ * it was never designed to detect all browsers.
509
+ * The change will come in 2017 in the 3.x release for PHP7.
510
+ *
511
+ * @var array
512
+ */
513
+ protected static $browsers = array(
514
+ //'Vivaldi' => 'Vivaldi',
515
+ // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
516
+ 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
517
+ 'Dolfin' => '\bDolfin\b',
518
+ 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
519
+ 'Skyfire' => 'Skyfire',
520
+ 'Edge' => 'Mobile Safari/[.0-9]* Edge',
521
+ 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
522
+ 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS',
523
+ 'Bolt' => 'bolt',
524
+ 'TeaShark' => 'teashark',
525
+ 'Blazer' => 'Blazer',
526
+ // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
527
+ 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
528
+ // http://en.wikipedia.org/wiki/Midori_(web_browser)
529
+ //'Midori' => 'midori',
530
+ //'Tizen' => 'Tizen',
531
+ 'UCBrowser' => 'UC.*Browser|UCWEB',
532
+ 'baiduboxapp' => 'baiduboxapp',
533
+ 'baidubrowser' => 'baidubrowser',
534
+ // https://github.com/serbanghita/Mobile-Detect/issues/7
535
+ 'DiigoBrowser' => 'DiigoBrowser',
536
+ // http://www.puffinbrowser.com/index.php
537
+ 'Puffin' => 'Puffin',
538
+ // http://mercury-browser.com/index.html
539
+ 'Mercury' => '\bMercury\b',
540
+ // http://en.wikipedia.org/wiki/Obigo_Browser
541
+ 'ObigoBrowser' => 'Obigo',
542
+ // http://en.wikipedia.org/wiki/NetFront
543
+ 'NetFront' => 'NF-Browser',
544
+ // @reference: http://en.wikipedia.org/wiki/Minimo
545
+ // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
546
+ 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
547
+ // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser)
548
+ 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon',
549
+ );
550
+
551
+ /**
552
+ * Utilities.
553
+ *
554
+ * @var array
555
+ */
556
+ protected static $utilities = array(
557
+ // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
558
+ // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
559
+ // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
560
+ // https://developers.facebook.com/docs/sharing/best-practices
561
+ 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom',
562
+ 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2',
563
+ 'DesktopMode' => 'WPDesktop',
564
+ 'TV' => 'SonyDTV|HbbTV', // experimental
565
+ 'WebKit' => '(webkit)[ /]([\w.]+)',
566
+ // @todo: Include JXD consoles.
567
+ 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b',
568
+ 'Watch' => 'SM-V700',
569
+ );
570
+
571
+ /**
572
+ * All possible HTTP headers that represent the
573
+ * User-Agent string.
574
+ *
575
+ * @var array
576
+ */
577
+ protected static $uaHttpHeaders = array(
578
+ // The default User-Agent string.
579
+ 'HTTP_USER_AGENT',
580
+ // Header can occur on devices using Opera Mini.
581
+ 'HTTP_X_OPERAMINI_PHONE_UA',
582
+ // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
583
+ 'HTTP_X_DEVICE_USER_AGENT',
584
+ 'HTTP_X_ORIGINAL_USER_AGENT',
585
+ 'HTTP_X_SKYFIRE_PHONE',
586
+ 'HTTP_X_BOLT_PHONE_UA',
587
+ 'HTTP_DEVICE_STOCK_UA',
588
+ 'HTTP_X_UCBROWSER_DEVICE_UA'
589
+ );
590
+
591
+ /**
592
+ * The individual segments that could exist in a User-Agent string. VER refers to the regular
593
+ * expression defined in the constant self::VER.
594
+ *
595
+ * @var array
596
+ */
597
+ protected static $properties = array(
598
+
599
+ // Build
600
+ 'Mobile' => 'Mobile/[VER]',
601
+ 'Build' => 'Build/[VER]',
602
+ 'Version' => 'Version/[VER]',
603
+ 'VendorID' => 'VendorID/[VER]',
604
+
605
+ // Devices
606
+ 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
607
+ 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
608
+ 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
609
+ //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
610
+ 'Kindle' => 'Kindle/[VER]',
611
+
612
+ // Browser
613
+ 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
614
+ 'Coast' => array('Coast/[VER]'),
615
+ 'Dolfin' => 'Dolfin/[VER]',
616
+ // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
617
+ 'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'),
618
+ 'Fennec' => 'Fennec/[VER]',
619
+ // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
620
+ // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx
621
+ 'Edge' => 'Edge/[VER]',
622
+ 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'),
623
+ // http://en.wikipedia.org/wiki/NetFront
624
+ 'NetFront' => 'NetFront/[VER]',
625
+ 'NokiaBrowser' => 'NokiaBrowser/[VER]',
626
+ 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
627
+ 'Opera Mini' => 'Opera Mini/[VER]',
628
+ 'Opera Mobi' => 'Version/[VER]',
629
+ 'UC Browser' => 'UC Browser[VER]',
630
+ 'MQQBrowser' => 'MQQBrowser/[VER]',
631
+ 'MicroMessenger' => 'MicroMessenger/[VER]',
632
+ 'baiduboxapp' => 'baiduboxapp/[VER]',
633
+ 'baidubrowser' => 'baidubrowser/[VER]',
634
+ 'SamsungBrowser' => 'SamsungBrowser/[VER]',
635
+ 'Iron' => 'Iron/[VER]',
636
+ // @note: Safari 7534.48.3 is actually Version 5.1.
637
+ // @note: On BlackBerry the Version is overwriten by the OS.
638
+ 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
639
+ 'Skyfire' => 'Skyfire/[VER]',
640
+ 'Tizen' => 'Tizen/[VER]',
641
+ 'Webkit' => 'webkit[ /][VER]',
642
+ 'PaleMoon' => 'PaleMoon/[VER]',
643
+
644
+ // Engine
645
+ 'Gecko' => 'Gecko/[VER]',
646
+ 'Trident' => 'Trident/[VER]',
647
+ 'Presto' => 'Presto/[VER]',
648
+ 'Goanna' => 'Goanna/[VER]',
649
+
650
+ // OS
651
+ 'iOS' => ' \bi?OS\b [VER][ ;]{1}',
652
+ 'Android' => 'Android [VER]',
653
+ 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
654
+ 'BREW' => 'BREW [VER]',
655
+ 'Java' => 'Java/[VER]',
656
+ // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
657
+ // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
658
+ 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
659
+ 'Windows Phone' => 'Windows Phone [VER]',
660
+ 'Windows CE' => 'Windows CE/[VER]',
661
+ // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
662
+ 'Windows NT' => 'Windows NT [VER]',
663
+ 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
664
+ 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
665
+ );
666
+
667
+ /**
668
+ * Construct an instance of this class.
669
+ *
670
+ * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
671
+ * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
672
+ * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
673
+ * from the $headers array instead.
674
+ */
675
+ public function __construct(
676
+ array $headers = null,
677
+ $userAgent = null
678
+ ) {
679
+ $this->setHttpHeaders($headers);
680
+ $this->setUserAgent($userAgent);
681
+ }
682
+
683
+ /**
684
+ * Get the current script version.
685
+ * This is useful for the demo.php file,
686
+ * so people can check on what version they are testing
687
+ * for mobile devices.
688
+ *
689
+ * @return string The version number in semantic version format.
690
+ */
691
+ public static function getScriptVersion()
692
+ {
693
+ return self::VERSION;
694
+ }
695
+
696
+ /**
697
+ * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
698
+ *
699
+ * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
700
+ * the headers. The default null is left for backwards compatibility.
701
+ */
702
+ public function setHttpHeaders($httpHeaders = null)
703
+ {
704
+ // use global _SERVER if $httpHeaders aren't defined
705
+ if (!is_array($httpHeaders) || !count($httpHeaders)) {
706
+ $httpHeaders = $_SERVER;
707
+ }
708
+
709
+ // clear existing headers
710
+ $this->httpHeaders = array();
711
+
712
+ // Only save HTTP headers. In PHP land, that means only _SERVER vars that
713
+ // start with HTTP_.
714
+ foreach ($httpHeaders as $key => $value) {
715
+ if (substr($key, 0, 5) === 'HTTP_') {
716
+ $this->httpHeaders[$key] = $value;
717
+ }
718
+ }
719
+
720
+ // In case we're dealing with CloudFront, we need to know.
721
+ $this->setCfHeaders($httpHeaders);
722
+ }
723
+
724
+ /**
725
+ * Retrieves the HTTP headers.
726
+ *
727
+ * @return array
728
+ */
729
+ public function getHttpHeaders()
730
+ {
731
+ return $this->httpHeaders;
732
+ }
733
+
734
+ /**
735
+ * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
736
+ * Simply null is returned.
737
+ *
738
+ * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
739
+ * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
740
+ * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
741
+ *
742
+ * @return string|null The value of the header.
743
+ */
744
+ public function getHttpHeader($header)
745
+ {
746
+ // are we using PHP-flavored headers?
747
+ if (strpos($header, '_') === false) {
748
+ $header = str_replace('-', '_', $header);
749
+ $header = strtoupper($header);
750
+ }
751
+
752
+ // test the alternate, too
753
+ $altHeader = 'HTTP_' . $header;
754
+
755
+ //Test both the regular and the HTTP_ prefix
756
+ if (isset($this->httpHeaders[$header])) {
757
+ return $this->httpHeaders[$header];
758
+ } elseif (isset($this->httpHeaders[$altHeader])) {
759
+ return $this->httpHeaders[$altHeader];
760
+ }
761
+
762
+ return null;
763
+ }
764
+
765
+ public function getMobileHeaders()
766
+ {
767
+ return self::$mobileHeaders;
768
+ }
769
+
770
+ /**
771
+ * Get all possible HTTP headers that
772
+ * can contain the User-Agent string.
773
+ *
774
+ * @return array List of HTTP headers.
775
+ */
776
+ public function getUaHttpHeaders()
777
+ {
778
+ return self::$uaHttpHeaders;
779
+ }
780
+
781
+
782
+ /**
783
+ * Set CloudFront headers
784
+ * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
785
+ *
786
+ * @param array $cfHeaders List of HTTP headers
787
+ *
788
+ * @return boolean If there were CloudFront headers to be set
789
+ */
790
+ public function setCfHeaders($cfHeaders = null) {
791
+ // use global _SERVER if $cfHeaders aren't defined
792
+ if (!is_array($cfHeaders) || !count($cfHeaders)) {
793
+ $cfHeaders = $_SERVER;
794
+ }
795
+
796
+ // clear existing headers
797
+ $this->cloudfrontHeaders = array();
798
+
799
+ // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that
800
+ // start with cloudfront-.
801
+ $response = false;
802
+ foreach ($cfHeaders as $key => $value) {
803
+ if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') {
804
+ $this->cloudfrontHeaders[strtoupper($key)] = $value;
805
+ $response = true;
806
+ }
807
+ }
808
+
809
+ return $response;
810
+ }
811
+
812
+ /**
813
+ * Retrieves the cloudfront headers.
814
+ *
815
+ * @return array
816
+ */
817
+ public function getCfHeaders()
818
+ {
819
+ return $this->cloudfrontHeaders;
820
+ }
821
+
822
+ /**
823
+ * Set the User-Agent to be used.
824
+ *
825
+ * @param string $userAgent The user agent string to set.
826
+ *
827
+ * @return string|null
828
+ */
829
+ public function setUserAgent($userAgent = null)
830
+ {
831
+ // Invalidate cache due to #375
832
+ $this->cache = array();
833
+
834
+ if (false === empty($userAgent)) {
835
+ return $this->userAgent = $userAgent;
836
+ } else {
837
+ $this->userAgent = null;
838
+ foreach ($this->getUaHttpHeaders() as $altHeader) {
839
+ if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
840
+ $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
841
+ }
842
+ }
843
+
844
+ if (!empty($this->userAgent)) {
845
+ return $this->userAgent = trim($this->userAgent);
846
+ }
847
+ }
848
+
849
+ if (count($this->getCfHeaders()) > 0) {
850
+ return $this->userAgent = 'Amazon CloudFront';
851
+ }
852
+ return $this->userAgent = null;
853
+ }
854
+
855
+ /**
856
+ * Retrieve the User-Agent.
857
+ *
858
+ * @return string|null The user agent if it's set.
859
+ */
860
+ public function getUserAgent()
861
+ {
862
+ return $this->userAgent;
863
+ }
864
+
865
+ /**
866
+ * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
867
+ * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
868
+ *
869
+ * @deprecated since version 2.6.9
870
+ *
871
+ * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
872
+ * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
873
+ */
874
+ public function setDetectionType($type = null)
875
+ {
876
+ if ($type === null) {
877
+ $type = self::DETECTION_TYPE_MOBILE;
878
+ }
879
+
880
+ if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) {
881
+ return;
882
+ }
883
+
884
+ $this->detectionType = $type;
885
+ }
886
+
887
+ public function getMatchingRegex()
888
+ {
889
+ return $this->matchingRegex;
890
+ }
891
+
892
+ public function getMatchesArray()
893
+ {
894
+ return $this->matchesArray;
895
+ }
896
+
897
+ /**
898
+ * Retrieve the list of known phone devices.
899
+ *
900
+ * @return array List of phone devices.
901
+ */
902
+ public static function getPhoneDevices()
903
+ {
904
+ return self::$phoneDevices;
905
+ }
906
+
907
+ /**
908
+ * Retrieve the list of known tablet devices.
909
+ *
910
+ * @return array List of tablet devices.
911
+ */
912
+ public static function getTabletDevices()
913
+ {
914
+ return self::$tabletDevices;
915
+ }
916
+
917
+ /**
918
+ * Alias for getBrowsers() method.
919
+ *
920
+ * @return array List of user agents.
921
+ */
922
+ public static function getUserAgents()
923
+ {
924
+ return self::getBrowsers();
925
+ }
926
+
927
+ /**
928
+ * Retrieve the list of known browsers. Specifically, the user agents.
929
+ *
930
+ * @return array List of browsers / user agents.
931
+ */
932
+ public static function getBrowsers()
933
+ {
934
+ return self::$browsers;
935
+ }
936
+
937
+ /**
938
+ * Retrieve the list of known utilities.
939
+ *
940
+ * @return array List of utilities.
941
+ */
942
+ public static function getUtilities()
943
+ {
944
+ return self::$utilities;
945
+ }
946
+
947
+ /**
948
+ * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
949
+ *
950
+ * @deprecated since version 2.6.9
951
+ *
952
+ * @return array All the rules (but not extended).
953
+ */
954
+ public static function getMobileDetectionRules()
955
+ {
956
+ static $rules;
957
+
958
+ if (!$rules) {
959
+ $rules = array_merge(
960
+ self::$phoneDevices,
961
+ self::$tabletDevices,
962
+ self::$operatingSystems,
963
+ self::$browsers
964
+ );
965
+ }
966
+
967
+ return $rules;
968
+
969
+ }
970
+
971
+ /**
972
+ * Method gets the mobile detection rules + utilities.
973
+ * The reason this is separate is because utilities rules
974
+ * don't necessary imply mobile. This method is used inside
975
+ * the new $detect->is('stuff') method.
976
+ *
977
+ * @deprecated since version 2.6.9
978
+ *
979
+ * @return array All the rules + extended.
980
+ */
981
+ public function getMobileDetectionRulesExtended()
982
+ {
983
+ static $rules;
984
+
985
+ if (!$rules) {
986
+ // Merge all rules together.
987
+ $rules = array_merge(
988
+ self::$phoneDevices,
989
+ self::$tabletDevices,
990
+ self::$operatingSystems,
991
+ self::$browsers,
992
+ self::$utilities
993
+ );
994
+ }
995
+
996
+ return $rules;
997
+ }
998
+
999
+ /**
1000
+ * Retrieve the current set of rules.
1001
+ *
1002
+ * @deprecated since version 2.6.9
1003
+ *
1004
+ * @return array
1005
+ */
1006
+ public function getRules()
1007
+ {
1008
+ if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
1009
+ return self::getMobileDetectionRulesExtended();
1010
+ } else {
1011
+ return self::getMobileDetectionRules();
1012
+ }
1013
+ }
1014
+
1015
+ /**
1016
+ * Retrieve the list of mobile operating systems.
1017
+ *
1018
+ * @return array The list of mobile operating systems.
1019
+ */
1020
+ public static function getOperatingSystems()
1021
+ {
1022
+ return self::$operatingSystems;
1023
+ }
1024
+
1025
+ /**
1026
+ * Check the HTTP headers for signs of mobile.
1027
+ * This is the fastest mobile check possible; it's used
1028
+ * inside isMobile() method.
1029
+ *
1030
+ * @return bool
1031
+ */
1032
+ public function checkHttpHeadersForMobile()
1033
+ {
1034
+
1035
+ foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
1036
+ if (isset($this->httpHeaders[$mobileHeader])) {
1037
+ if (is_array($matchType['matches'])) {
1038
+ foreach ($matchType['matches'] as $_match) {
1039
+ if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) {
1040
+ return true;
1041
+ }
1042
+ }
1043
+
1044
+ return false;
1045
+ } else {
1046
+ return true;
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ return false;
1052
+
1053
+ }
1054
+
1055
+ /**
1056
+ * Magic overloading method.
1057
+ *
1058
+ * @method boolean is[...]()
1059
+ * @param string $name
1060
+ * @param array $arguments
1061
+ * @return mixed
1062
+ * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
1063
+ */
1064
+ public function __call($name, $arguments)
1065
+ {
1066
+ // make sure the name starts with 'is', otherwise
1067
+ if (substr($name, 0, 2) !== 'is') {
1068
+ throw new BadMethodCallException("No such method exists: $name");
1069
+ }
1070
+
1071
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1072
+
1073
+ $key = substr($name, 2);
1074
+
1075
+ return $this->matchUAAgainstKey($key);
1076
+ }
1077
+
1078
+ /**
1079
+ * Find a detection rule that matches the current User-agent.
1080
+ *
1081
+ * @param null $userAgent deprecated
1082
+ * @return boolean
1083
+ */
1084
+ protected function matchDetectionRulesAgainstUA($userAgent = null)
1085
+ {
1086
+ // Begin general search.
1087
+ foreach ($this->getRules() as $_regex) {
1088
+ if (empty($_regex)) {
1089
+ continue;
1090
+ }
1091
+
1092
+ if ($this->match($_regex, $userAgent)) {
1093
+ return true;
1094
+ }
1095
+ }
1096
+
1097
+ return false;
1098
+ }
1099
+
1100
+ /**
1101
+ * Search for a certain key in the rules array.
1102
+ * If the key is found then try to match the corresponding
1103
+ * regex against the User-Agent.
1104
+ *
1105
+ * @param string $key
1106
+ *
1107
+ * @return boolean
1108
+ */
1109
+ protected function matchUAAgainstKey($key)
1110
+ {
1111
+ // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1112
+ $key = strtolower($key);
1113
+ if (false === isset($this->cache[$key])) {
1114
+
1115
+ // change the keys to lower case
1116
+ $_rules = array_change_key_case($this->getRules());
1117
+
1118
+ if (false === empty($_rules[$key])) {
1119
+ $this->cache[$key] = $this->match($_rules[$key]);
1120
+ }
1121
+
1122
+ if (false === isset($this->cache[$key])) {
1123
+ $this->cache[$key] = false;
1124
+ }
1125
+ }
1126
+
1127
+ return $this->cache[$key];
1128
+ }
1129
+
1130
+ /**
1131
+ * Check if the device is mobile.
1132
+ * Returns true if any type of mobile device detected, including special ones
1133
+ * @param null $userAgent deprecated
1134
+ * @param null $httpHeaders deprecated
1135
+ * @return bool
1136
+ */
1137
+ public function isMobile($userAgent = null, $httpHeaders = null)
1138
+ {
1139
+
1140
+ if ($httpHeaders) {
1141
+ $this->setHttpHeaders($httpHeaders);
1142
+ }
1143
+
1144
+ if ($userAgent) {
1145
+ $this->setUserAgent($userAgent);
1146
+ }
1147
+
1148
+ // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1149
+ if ($this->getUserAgent() === 'Amazon CloudFront') {
1150
+ $cfHeaders = $this->getCfHeaders();
1151
+ if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') {
1152
+ return true;
1153
+ }
1154
+ }
1155
+
1156
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1157
+
1158
+ if ($this->checkHttpHeadersForMobile()) {
1159
+ return true;
1160
+ } else {
1161
+ return $this->matchDetectionRulesAgainstUA();
1162
+ }
1163
+
1164
+ }
1165
+
1166
+ /**
1167
+ * Check if the device is a tablet.
1168
+ * Return true if any type of tablet device is detected.
1169
+ *
1170
+ * @param string $userAgent deprecated
1171
+ * @param array $httpHeaders deprecated
1172
+ * @return bool
1173
+ */
1174
+ public function isTablet($userAgent = null, $httpHeaders = null)
1175
+ {
1176
+ // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1177
+ if ($this->getUserAgent() === 'Amazon CloudFront') {
1178
+ $cfHeaders = $this->getCfHeaders();
1179
+ if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') {
1180
+ return true;
1181
+ }
1182
+ }
1183
+
1184
+ $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1185
+
1186
+ foreach (self::$tabletDevices as $_regex) {
1187
+ if ($this->match($_regex, $userAgent)) {
1188
+ return true;
1189
+ }
1190
+ }
1191
+
1192
+ return false;
1193
+ }
1194
+
1195
+ /**
1196
+ * This method checks for a certain property in the
1197
+ * userAgent.
1198
+ * @todo: The httpHeaders part is not yet used.
1199
+ *
1200
+ * @param string $key
1201
+ * @param string $userAgent deprecated
1202
+ * @param string $httpHeaders deprecated
1203
+ * @return bool|int|null
1204
+ */
1205
+ public function is($key, $userAgent = null, $httpHeaders = null)
1206
+ {
1207
+ // Set the UA and HTTP headers only if needed (eg. batch mode).
1208
+ if ($httpHeaders) {
1209
+ $this->setHttpHeaders($httpHeaders);
1210
+ }
1211
+
1212
+ if ($userAgent) {
1213
+ $this->setUserAgent($userAgent);
1214
+ }
1215
+
1216
+ $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
1217
+
1218
+ return $this->matchUAAgainstKey($key);
1219
+ }
1220
+
1221
+ /**
1222
+ * Some detection rules are relative (not standard),
1223
+ * because of the diversity of devices, vendors and
1224
+ * their conventions in representing the User-Agent or
1225
+ * the HTTP headers.
1226
+ *
1227
+ * This method will be used to check custom regexes against
1228
+ * the User-Agent string.
1229
+ *
1230
+ * @param $regex
1231
+ * @param string $userAgent
1232
+ * @return bool
1233
+ *
1234
+ * @todo: search in the HTTP headers too.
1235
+ */
1236
+ public function match($regex, $userAgent = null)
1237
+ {
1238
+ $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches);
1239
+ // If positive match is found, store the results for debug.
1240
+ if ($match) {
1241
+ $this->matchingRegex = $regex;
1242
+ $this->matchesArray = $matches;
1243
+ }
1244
+
1245
+ return $match;
1246
+ }
1247
+
1248
+ /**
1249
+ * Get the properties array.
1250
+ *
1251
+ * @return array
1252
+ */
1253
+ public static function getProperties()
1254
+ {
1255
+ return self::$properties;
1256
+ }
1257
+
1258
+ /**
1259
+ * Prepare the version number.
1260
+ *
1261
+ * @todo Remove the error supression from str_replace() call.
1262
+ *
1263
+ * @param string $ver The string version, like "2.6.21.2152";
1264
+ *
1265
+ * @return float
1266
+ */
1267
+ public function prepareVersionNo($ver)
1268
+ {
1269
+ $ver = str_replace(array('_', ' ', '/'), '.', $ver);
1270
+ $arrVer = explode('.', $ver, 2);
1271
+
1272
+ if (isset($arrVer[1])) {
1273
+ $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
1274
+ }
1275
+
1276
+ return (float) implode('.', $arrVer);
1277
+ }
1278
+
1279
+ /**
1280
+ * Check the version of the given property in the User-Agent.
1281
+ * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1282
+ *
1283
+ * @param string $propertyName The name of the property. See self::getProperties() array
1284
+ * keys for all possible properties.
1285
+ * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1286
+ * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1287
+ * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1288
+ * invalid parameter will default to the this type as well.
1289
+ *
1290
+ * @return string|float The version of the property we are trying to extract.
1291
+ */
1292
+ public function version($propertyName, $type = self::VERSION_TYPE_STRING)
1293
+ {
1294
+ if (empty($propertyName)) {
1295
+ return false;
1296
+ }
1297
+
1298
+ // set the $type to the default if we don't recognize the type
1299
+ if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) {
1300
+ $type = self::VERSION_TYPE_STRING;
1301
+ }
1302
+
1303
+ $properties = self::getProperties();
1304
+
1305
+ // Check if the property exists in the properties array.
1306
+ if (true === isset($properties[$propertyName])) {
1307
+
1308
+ // Prepare the pattern to be matched.
1309
+ // Make sure we always deal with an array (string is converted).
1310
+ $properties[$propertyName] = (array) $properties[$propertyName];
1311
+
1312
+ foreach ($properties[$propertyName] as $propertyMatchString) {
1313
+
1314
+ $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
1315
+
1316
+ // Identify and extract the version.
1317
+ preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match);
1318
+
1319
+ if (false === empty($match[1])) {
1320
+ $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]);
1321
+
1322
+ return $version;
1323
+ }
1324
+
1325
+ }
1326
+
1327
+ }
1328
+
1329
+ return false;
1330
+ }
1331
+
1332
+ /**
1333
+ * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1334
+ *
1335
+ * @return string One of the self::MOBILE_GRADE_* constants.
1336
+ */
1337
+ public function mobileGrade()
1338
+ {
1339
+ $isMobile = $this->isMobile();
1340
+
1341
+ if (
1342
+ // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0)
1343
+ $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1344
+ $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1345
+ $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1346
+
1347
+ // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
1348
+ // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1349
+ // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1350
+ // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1351
+ ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1352
+
1353
+ // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8)
1354
+ $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 ||
1355
+
1356
+ // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1357
+ $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 ||
1358
+ // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1359
+ $this->match('Playbook.*Tablet') ||
1360
+
1361
+ // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1362
+ ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) ||
1363
+ // Palm WebOS 3.0 - Tested on HP TouchPad
1364
+ $this->match('hp.*TouchPad') ||
1365
+
1366
+ // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1367
+ ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) ||
1368
+
1369
+ // Chrome for Android - Tested on Android 4.0, 4.1 device
1370
+ ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) ||
1371
+
1372
+ // Skyfire 4.1 - Tested on Android 2.3 device
1373
+ ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1374
+
1375
+ // Opera Mobile 11.5-12: Tested on Android 2.3
1376
+ ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) ||
1377
+
1378
+ // Meego 1.2 - Tested on Nokia 950 and N9
1379
+ $this->is('MeeGoOS') ||
1380
+
1381
+ // Tizen (pre-release) - Tested on early hardware
1382
+ $this->is('Tizen') ||
1383
+
1384
+ // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1385
+ // @todo: more tests here!
1386
+ $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 ||
1387
+
1388
+ // UC Browser - Tested on Android 2.3 device
1389
+ ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1390
+
1391
+ // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1392
+ ( $this->match('Kindle Fire') ||
1393
+ $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) ||
1394
+
1395
+ // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1396
+ $this->is('AndroidOS') && $this->is('NookTablet') ||
1397
+
1398
+ // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1399
+ $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile ||
1400
+
1401
+ // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1402
+ $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile ||
1403
+
1404
+ // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1405
+ $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile ||
1406
+
1407
+ // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1408
+ $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile ||
1409
+
1410
+ // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1411
+ $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile
1412
+ ){
1413
+ return self::MOBILE_GRADE_A;
1414
+ }
1415
+
1416
+ if (
1417
+ $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1418
+ $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 ||
1419
+ $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 ||
1420
+
1421
+ // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1422
+ $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1423
+
1424
+ //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1425
+ ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 &&
1426
+ ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) ||
1427
+
1428
+ // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1429
+ $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1430
+
1431
+ // @todo: report this (tested on Nokia N71)
1432
+ $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS')
1433
+ ){
1434
+ return self::MOBILE_GRADE_B;
1435
+ }
1436
+
1437
+ if (
1438
+ // Blackberry 4.x - Tested on the Curve 8330
1439
+ $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 ||
1440
+ // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1441
+ $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 ||
1442
+
1443
+ // Tested on original iPhone (3.1), iPhone 3 (3.2)
1444
+ $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1445
+ $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1446
+ $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1447
+
1448
+ // Internet Explorer 7 and older - Tested on Windows XP
1449
+ $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile
1450
+ ){
1451
+ return self::MOBILE_GRADE_C;
1452
+ }
1453
+
1454
+ // All older smartphone platforms and featurephones - Any device that doesn't support media queries
1455
+ // will receive the basic, C grade experience.
1456
+ return self::MOBILE_GRADE_C;
1457
+ }
1458
+ }
classes/helpers/recapcha.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class recapchaPps {
3
+ private $_publicKey = '6LfUotgSAAAAAL4pqsHxE8sx6Cz8o7AEc_JjtROD';
4
+ private $_privateKey = '6LfUotgSAAAAACFAM1TMpIsLiQsfDmV-mRNfQg1n';
5
+
6
+ public function __construct() {
7
+ if(!function_exists('recaptcha_get_html')) { // In case if this lib was already included by another plugin
8
+ importPps(PPS_HELPERS_DIR. 'recaptchalib.php');
9
+ }
10
+ }
11
+ static public function getInstance() {
12
+ static $instance = NULL;
13
+ if(empty($instance)) {
14
+ $instance = new recapchaPps();
15
+ }
16
+ return $instance;
17
+ }
18
+ static public function _() {
19
+ return self::getInstance();
20
+ }
21
+ public function getHtml() {
22
+ if(reqPps::getVar('reqType') == 'ajax') {
23
+ $divId = 'toeRecapcha'. mt_rand(1, 9999);
24
+ return '<div id="'. $divId. '"></div>'.
25
+ '<script type="text/javascript">
26
+ // <!--
27
+ Recaptcha.create("'. $this->_publicKey. '",
28
+ "'. $divId. '",
29
+ {
30
+ theme: "red",
31
+ callback: Recaptcha.focus_response_field
32
+ }
33
+ );
34
+ // -->
35
+ </script>';
36
+ } else {
37
+ return recaptcha_get_html($this->_publicKey, null, true);
38
+ }
39
+ }
40
+ public function check() {
41
+ $resp = recaptcha_check_answer($this->_privateKey,
42
+ $_SERVER['REMOTE_ADDR'],
43
+ reqPps::getVar('recaptcha_challenge_field'),
44
+ reqPps::getVar('recaptcha_response_field'));
45
+ return $resp->is_valid;
46
+ }
47
+ }
classes/helpers/recaptchalib.php ADDED
@@ -0,0 +1,298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ * - Documentation and latest version
5
+ * http://recaptcha.net/plugins/php/
6
+ * - Get a reCAPTCHA API Key
7
+ * https://www.google.com/recaptcha/admin/create
8
+ * - Discussion group
9
+ * http://groups.google.com/group/recaptcha
10
+ *
11
+ * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
12
+ * AUTHORS:
13
+ * Mike Crawford
14
+ * Ben Maurer
15
+ *
16
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ * of this software and associated documentation files (the "Software"), to deal
18
+ * in the Software without restriction, including without limitation the rights
19
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ * copies of the Software, and to permit persons to whom the Software is
21
+ * furnished to do so, subject to the following conditions:
22
+ *
23
+ * The above copyright notice and this permission notice shall be included in
24
+ * all copies or substantial portions of the Software.
25
+ *
26
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
+ * THE SOFTWARE.
33
+ */
34
+
35
+ /**
36
+ * The reCAPTCHA server URL's
37
+ */
38
+ define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
39
+ define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
40
+ define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
41
+
42
+ /**
43
+ * Encodes the given data into a query string format
44
+ * @param $data - array of string elements to be encoded
45
+ * @return string - encoded request
46
+ */
47
+ function _recaptcha_qsencode ($data) {
48
+ $req = "";
49
+ foreach ( $data as $key => $value )
50
+ $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
51
+
52
+ // Cut the last '&'
53
+ $req=substr($req,0,strlen($req)-1);
54
+ return $req;
55
+ }
56
+
57
+
58
+
59
+ /**
60
+ * Submits an HTTP POST to a reCAPTCHA server
61
+ * @param string $host
62
+ * @param string $path
63
+ * @param array $data
64
+ * @param int port
65
+ * @return array response
66
+ */
67
+ function _recaptcha_http_post($host, $path, $data, $port = 80) {
68
+
69
+ $req = _recaptcha_qsencode ($data);
70
+
71
+ $http_request = "POST $path HTTP/1.0\r\n";
72
+ $http_request .= "Host: $host\r\n";
73
+ $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
74
+ $http_request .= "Content-Length: " . strlen($req) . "\r\n";
75
+ $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
76
+ $http_request .= "\r\n";
77
+ $http_request .= $req;
78
+
79
+ $response = '';
80
+ if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
81
+ die ('Could not open socket');
82
+ }
83
+
84
+ fwrite($fs, $http_request);
85
+
86
+ while ( !feof($fs) )
87
+ $response .= fgets($fs, 1160); // One TCP-IP packet
88
+ fclose($fs);
89
+ $response = explode("\r\n\r\n", $response, 2);
90
+
91
+ return $response;
92
+ }
93
+
94
+
95
+
96
+ /**
97
+ * Gets the challenge HTML (javascript and non-javascript version).
98
+ * This is called from the browser, and the resulting reCAPTCHA HTML widget
99
+ * is embedded within the HTML form it was called from.
100
+ * @param string $pubkey A public key for reCAPTCHA
101
+ * @param string $error The error given by reCAPTCHA (optional, default is null)
102
+ * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
103
+
104
+ * @return string - The HTML to be embedded in the user's form.
105
+ */
106
+ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
107
+ {
108
+ if ($pubkey == null || $pubkey == '') {
109
+ die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
110
+ }
111
+
112
+ if ($use_ssl) {
113
+ $server = RECAPTCHA_API_SECURE_SERVER;
114
+ } else {
115
+ $server = RECAPTCHA_API_SERVER;
116
+ }
117
+
118
+ $errorpart = "";
119
+ if ($error) {
120
+ $errorpart = "&amp;error=" . $error;
121
+ }
122
+
123
+ return '<script type="text/javascript" src="'. $server . '/challenge?width=200&amp;k=' . $pubkey . $errorpart . '"></script>
124
+
125
+ <noscript>
126
+ <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
127
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
128
+ <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
129
+ </noscript>'. '<style type="text/css">
130
+ #recaptcha_image,
131
+ #recaptcha_image img
132
+ {
133
+ width: auto !important;
134
+ cursor: pointer;
135
+ }
136
+ #recaptcha_image img:hover
137
+ {
138
+ position: absolute;
139
+ width: 300px !important;
140
+ }
141
+ .recaptcha_only_if_image,
142
+ .recaptcha_only_if_audio
143
+ {
144
+ display: block;
145
+ }
146
+ #recaptcha_area, #recaptcha_table {
147
+ width: auto !important;
148
+ }
149
+ </style>';
150
+ }
151
+
152
+
153
+
154
+
155
+ /**
156
+ * A ReCaptchaResponse is returned from recaptcha_check_answer()
157
+ */
158
+ class ReCaptchaResponse {
159
+ var $is_valid;
160
+ var $error;
161
+ }
162
+
163
+
164
+ /**
165
+ * Calls an HTTP POST function to verify if the user's guess was correct
166
+ * @param string $privkey
167
+ * @param string $remoteip
168
+ * @param string $challenge
169
+ * @param string $response
170
+ * @param array $extra_params an array of extra variables to post to the server
171
+ * @return ReCaptchaResponse
172
+ */
173
+ function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
174
+ {
175
+ if ($privkey == null || $privkey == '') {
176
+ die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
177
+ }
178
+
179
+ if ($remoteip == null || $remoteip == '') {
180
+ die ("For security reasons, you must pass the remote ip to reCAPTCHA");
181
+ }
182
+
183
+
184
+
185
+ //discard spam submissions
186
+ if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
187
+ $recaptcha_response = new ReCaptchaResponse();
188
+ $recaptcha_response->is_valid = false;
189
+ $recaptcha_response->error = 'incorrect-captcha-sol';
190
+ return $recaptcha_response;
191
+ }
192
+
193
+ $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
194
+ array (
195
+ 'privatekey' => $privkey,
196
+ 'remoteip' => $remoteip,
197
+ 'challenge' => $challenge,
198
+ 'response' => $response
199
+ ) + $extra_params
200
+ );
201
+
202
+ $answers = explode ("\n", $response [1]);
203
+ $recaptcha_response = new ReCaptchaResponse();
204
+
205
+ if (trim ($answers [0]) == 'true') {
206
+ $recaptcha_response->is_valid = true;
207
+ }
208
+ else {
209
+ $recaptcha_response->is_valid = false;
210
+ $recaptcha_response->error = $answers [1];
211
+ }
212
+ return $recaptcha_response;
213
+
214
+ }
215
+
216
+ /**
217
+ * gets a URL where the user can sign up for reCAPTCHA. If your application
218
+ * has a configuration page where you enter a key, you should provide a link
219
+ * using this function.
220
+ * @param string $domain The domain where the page is hosted
221
+ * @param string $appname The name of your application
222
+ */
223
+ function recaptcha_get_signup_url ($domain = null, $appname = null) {
224
+ return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
225
+ }
226
+
227
+ function _recaptcha_aes_pad($val) {
228
+ $block_size = 16;
229
+ $numpad = $block_size - (strlen ($val) % $block_size);
230
+ return str_pad($val, strlen ($val) + $numpad, chr($numpad));
231
+ }
232
+
233
+ /* Mailhide related code */
234
+
235
+ function _recaptcha_aes_encrypt($val,$ky) {
236
+ if (! function_exists ("mcrypt_encrypt")) {
237
+ die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
238
+ }
239
+ $mode=MCRYPT_MODE_CBC;
240
+ $enc=MCRYPT_RIJNDAEL_128;
241
+ $val=_recaptcha_aes_pad($val);
242
+ return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
243
+ }
244
+
245
+
246
+ function _recaptcha_mailhide_urlbase64 ($x) {
247
+ return strtr(base64_encode ($x), '+/', '-_');
248
+ }
249
+
250
+ /* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
251
+ function recaptcha_mailhide_url($pubkey, $privkey, $email) {
252
+ if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
253
+ die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
254
+ "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
255
+ }
256
+
257
+
258
+ $ky = pack('H*', $privkey);
259
+ $cryptmail = _recaptcha_aes_encrypt ($email, $ky);
260
+
261
+ return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
262
+ }
263
+
264
+ /**
265
+ * gets the parts of the email to expose to the user.
266
+ * eg, given johndoe@example,com return ["john", "example.com"].
267
+ * the email is then displayed as john...@example.com
268
+ */
269
+ function _recaptcha_mailhide_email_parts ($email) {
270
+ $arr = preg_split("/@/", $email );
271
+
272
+ if (strlen ($arr[0]) <= 4) {
273
+ $arr[0] = substr ($arr[0], 0, 1);
274
+ } else if (strlen ($arr[0]) <= 6) {
275
+ $arr[0] = substr ($arr[0], 0, 3);
276
+ } else {
277
+ $arr[0] = substr ($arr[0], 0, 4);
278
+ }
279
+ return $arr;
280
+ }
281
+
282
+ /**
283
+ * Gets html to display an email address given a public an private key.
284
+ * to get a key, go to:
285
+ *
286
+ * http://www.google.com/recaptcha/mailhide/apikey
287
+ */
288
+ function recaptcha_mailhide_html($pubkey, $privkey, $email) {
289
+ $emailparts = _recaptcha_mailhide_email_parts ($email);
290
+ $url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
291
+
292
+ return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
293
+ "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
294
+
295
+ }
296
+
297
+
298
+ ?>
classes/html.php ADDED
@@ -0,0 +1,721 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class htmlPps {
3
+ static public $categoriesOptions = array();
4
+ static public $productsOptions = array();
5
+ static public function block($name, $params= array('attrs' => '', 'value' => '')){
6
+ $output .= '<p class="toe_'. self::nameToClassId($name). '">'.$params['value'].'</p>';
7
+ //$output .= self::hidden($name, $params);
8
+ return $output;
9
+ }
10
+ static public function nameToClassId($name, $params = array()) {
11
+ if(!empty($params) && isset($params['attrs']) && strpos($params['attrs'], 'id="') !== false) {
12
+ preg_match('/id="(.+)"/ui', $params['attrs'], $idMatches);
13
+ if($idMatches[1]) {
14
+ return $idMatches[1];
15
+ }
16
+ }
17
+ return str_replace(array('[', ']'), '', $name);
18
+ }
19
+ static public function textarea($name, $params = array('attrs' => '', 'value' => '', 'rows' => 3, 'cols' => 50)) {
20
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
21
+ $params['rows'] = isset($params['rows']) ? $params['rows'] : 3;
22
+ $params['cols'] = isset($params['cols']) ? $params['cols'] : 50;
23
+ if(isset($params['required']) && $params['required']) {
24
+ $params['attrs'] .= ' required '; // HTML5 "required" validation attr
25
+ }
26
+ if(isset($params['placeholder']) && $params['placeholder']) {
27
+ $params['attrs'] .= ' placeholder="'. $params['placeholder']. '"'; // HTML5 "required" validation attr
28
+ }
29
+ if(isset($params['disabled']) && $params['disabled']) {
30
+ $params['attrs'] .= ' disabled ';
31
+ }
32
+ if(isset($params['readonly']) && $params['readonly']) {
33
+ $params['attrs'] .= ' readonly ';
34
+ }
35
+ if(isset($params['auto_width']) && $params['auto_width']) {
36
+ unset($params['rows']);
37
+ unset($params['cols']);
38
+ }
39
+ return '<textarea name="'. $name. '" '
40
+ . (isset($params['attrs']) ? $params['attrs'] : '')
41
+ . (isset($params['rows']) ? ' rows="'. $params['rows']. '"' : '')
42
+ . (isset($params['cols']) ? ' cols="'. $params['cols']. '"' : '')
43
+ . '>'.
44
+ (isset($params['value']) ? $params['value'] : '').
45
+ '</textarea>';
46
+ }
47
+ static public function input($name, $params = array('attrs' => '', 'type' => 'text', 'value' => '')) {
48
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
49
+ $params['attrs'] .= self::_dataToAttrs($params);
50
+ if(isset($params['required']) && $params['required']) {
51
+ $params['attrs'] .= ' required '; // HTML5 "required" validation attr
52
+ }
53
+ if(isset($params['placeholder']) && $params['placeholder']) {
54
+ $params['attrs'] .= ' placeholder="'. $params['placeholder']. '"'; // HTML5 "required" validation attr
55
+ }
56
+ if(isset($params['disabled']) && $params['disabled']) {
57
+ $params['attrs'] .= ' disabled ';
58
+ }
59
+ if(isset($params['readonly']) && $params['readonly']) {
60
+ $params['attrs'] .= ' readonly ';
61
+ }
62
+ $params['value'] = isset($params['value']) ? $params['value'] : '';
63
+ return '<input type="'. $params['type']. '" name="'. $name. '" value="'. $params['value']. '" '. (isset($params['attrs']) ? $params['attrs'] : ''). ' />';
64
+ }
65
+ static private function _dataToAttrs($params) {
66
+ $res = '';
67
+ foreach($params as $k => $v) {
68
+ if(strpos($k, 'data-') === 0) {
69
+ $res .= ' '. $k. '="'. $v. '"';
70
+ }
71
+ }
72
+ return $res;
73
+ }
74
+ static public function text($name, $params = array('attrs' => '', 'value' => '')) {
75
+ $params['type'] = 'text';
76
+ return self::input($name, $params);
77
+ }
78
+ static public function email($name, $params = array('attrs' => '', 'value' => '')) {
79
+ $params['type'] = 'email';
80
+ return self::input($name, $params);
81
+ }
82
+ static public function reset($name, $params = array('attrs' => '', 'value' => '')) {
83
+ $params['type'] = 'reset';
84
+ return self::input($name, $params);
85
+ }
86
+ static public function password($name, $params = array('attrs' => '', 'value' => '')) {
87
+ $params['type'] = 'password';
88
+ return self::input($name, $params);
89
+ }
90
+ static public function hidden($name, $params = array('attrs' => '', 'value' => '')) {
91
+ $params['type'] = 'hidden';
92
+ return self::input($name, $params);
93
+ }
94
+ static public function checkbox($name, $params = array('attrs' => '', 'value' => '', 'checked' => '')) {
95
+ $params['type'] = 'checkbox';
96
+ if(isset($params['checked']) && $params['checked'])
97
+ $params['checked'] = 'checked';
98
+ if(!isset($params['value']) || $params['value'] === NULL)
99
+ $params['value'] = 1;
100
+ if(!isset($params['attrs']))
101
+ $params['attrs'] = '';
102
+ $params['attrs'] .= ' '. (isset($params['checked']) ? $params['checked'] : '');
103
+ return self::input($name, $params);
104
+ }
105
+ static public function checkboxlist($name, $params = array('options' => array(), 'attrs' => '', 'checked' => '', 'delim' => '<br />', 'usetable' => 5), $delim = '<br />') {
106
+ $out = '';
107
+ if(!strpos($name, '[]')) {
108
+ $name .= '[]';
109
+ }
110
+ $i = 0;
111
+ if($params['options']) {
112
+ if(!isset($params['delim']))
113
+ $params['delim'] = $delim;
114
+ if($params['usetable']) $out .= '<table><tr>';
115
+ foreach($params['options'] as $v) {
116
+ if($params['usetable']) {
117
+ if($i != 0 && $i%$params['usetable'] == 0) $out .= '</tr><tr>';
118
+ $out .= '<td>';
119
+ }
120
+ $out .= self::checkbox($name, array(
121
+ 'attrs' => $params['attrs'],
122
+ 'value' => $v['id'],
123
+ 'checked' => $v['checked']
124
+ ));
125
+ $out .= '&nbsp;'. $v['text']. $params['delim'];
126
+ if($params['usetable']) $out .= '</td>';
127
+ $i++;
128
+ }
129
+ if($params['usetable']) $out .= '</tr></table>';
130
+ }
131
+ return $out;
132
+ }
133
+ static public function timepicker($name, $params = array('attrs' => '', 'value' => '')) {
134
+ if(isset($params['id']) && !empty($params['id']))
135
+ $id = $params['id'];
136
+ else
137
+ $id = self::nameToClassId($name);
138
+ return self::input($name, array(
139
+ 'attrs' => 'id="'. $id. '" '. (isset($params['attrs']) ? $params['attrs'] : ''),
140
+ 'type' => 'text',
141
+ 'value' => $params['value']
142
+ )).'<script type="text/javascript">
143
+ // <!--
144
+ jQuery(document).ready(function(){
145
+ jQuery("#'. $id. '").timepicker('. json_encode($params). ');
146
+ });
147
+ // -->
148
+ </script>';
149
+ }
150
+ static public function datepicker($name, $params = array('attrs' => '', 'value' => '')) {
151
+ if(isset($params['id']) && !empty($params['id']))
152
+ $id = $params['id'];
153
+ else
154
+ $id = self::nameToClassId($name);
155
+ $params = array_merge(array(
156
+ 'dateFormat' => PPS_DATE_FORMAT_JS,
157
+ 'changeYear' => true,
158
+ 'yearRange' => '1905:'. (date('Y')+5),
159
+ ), $params);
160
+ return self::input($name, array(
161
+ 'attrs' => 'id="'. $id. '" '. (isset($params['attrs']) ? $params['attrs'] : ''),
162
+ 'type' => 'text',
163
+ 'value' => $params['value']
164
+ )).'<script type="text/javascript">
165
+ // <!--
166
+ jQuery(document).ready(function(){
167
+ jQuery("#'. $id. '").datepicker('. json_encode($params). ');
168
+ });
169
+ // -->
170
+ </script>';
171
+ }
172
+ static public function submit($name, $params = array('attrs' => '', 'value' => '')) {
173
+ $params['type'] = 'submit';
174
+ return self::input($name, $params);
175
+ }
176
+ static public function img($src, $usePlugPath = 1, $params = array('width' => '', 'height' => '', 'attrs' => '')) {
177
+ if($usePlugPath) $src = PPS_IMG_PATH. $src;
178
+ return '<img src="'.$src.'" '
179
+ .(isset($params['width']) ? 'width="'.$params['width'].'"' : '')
180
+ .' '
181
+ .(isset($params['height']) ? 'height="'.$params['height'].'"' : '')
182
+ .' '
183
+ .(isset($params['attrs']) ? $params['attrs'] : '').' />';
184
+ }
185
+ static public function selectbox($name, $params = array('attrs' => '', 'options' => array(), 'value' => '')) {
186
+ $out = '';
187
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
188
+ $params['attrs'] .= self::_dataToAttrs($params);
189
+ if(isset($params['required']) && $params['required']) {
190
+ $params['attrs'] .= ' required '; // HTML5 "required" validation attr
191
+ }
192
+ $out .= '<select name="'. $name. '" '. (isset($params['attrs']) ? $params['attrs'] : ''). '>';
193
+ if(!empty($params['options'])) {
194
+ foreach($params['options'] as $k => $v) {
195
+ $selected = (isset($params['value']) && $k == $params['value'] ? 'selected="true"' : '');
196
+ $out .= '<option value="'. $k. '" '. $selected. '>'. $v. '</option>';
197
+ }
198
+ }
199
+ $out .= '</select>';
200
+ return $out;
201
+ }
202
+ static public function selectlist($name, $params = array('attrs'=>'', 'size'=> 5, 'options' => array(), 'value' => '')) {
203
+ $out = '';
204
+ if(!strpos($name, '[]'))
205
+ $name .= '[]';
206
+ if (!isset($params['size']) || !is_numeric($params['size']) || $params['size'] == '') {
207
+ $params['size'] = 5;
208
+ }
209
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
210
+ $params['attrs'] .= self::_dataToAttrs($params);
211
+ $out .= '<select multiple="multiple" size="'.$params['size'].'" name="'.$name.'" '.$params['attrs'].'>';
212
+ $params['value'] = isset($params['value']) ? $params['value'] : array();
213
+ if(!empty($params['options'])) {
214
+ foreach($params['options'] as $k => $v) {
215
+ $selected = (in_array($k,(array)$params['value']) ? 'selected="true"' : '');
216
+ $out .= '<option value="'.$k.'" '.$selected.'>'.$v.'</option>';
217
+ }
218
+ }
219
+ $out .= '</select>';
220
+ return $out;
221
+ }
222
+ static public function file($name, $params = array()) {
223
+ $params['type'] = 'file';
224
+ return self::input($name, $params);
225
+ }
226
+ static public function ajaxfile($name, $params = array('url' => '', 'value' => '', 'fid' => '', 'buttonName' => '')) {
227
+ framePps::_()->addScript('ajaxupload', PPS_JS_PATH. 'ajaxupload.js');
228
+ $out = '';
229
+ if(strpos($params['url'], 'pl='. PPS_CODE) === false)
230
+ $params['url'] = uriPps::_(array('baseUrl' => $params['url'], 'pl' => PPS_CODE));
231
+ $out .= self::button(array('value' => __( empty($params['buttonName']) ? 'Upload' : $params['buttonName'] ), 'attrs' => 'id="toeUploadbut_'.$name.'" class="button button-large"'));
232
+ $display = (empty($params['value']) ? 'style="display: none;"' : '');
233
+ if(isset($params['preview']) && $params['preview'])
234
+ $out .= self::img($params['value'], 0, array('attrs' => 'id="prev_'.$name.'" '.$display.' class="previewpicture"'));
235
+ $out .= '<span class="delete_option" id="delete_'.$name.'" '.$display.'></span>';
236
+ $out .= '<script type="text/javascript">// <!--
237
+ jQuery(document).ready(function(){
238
+ new AjaxUpload("#toeUploadbut_'.$name.'", {
239
+ action: "'.$params['url'].'",
240
+ name: "'. $name. '" '.
241
+ (empty($params['data']) ? '' : ', data: '. $params['data']. '').
242
+ (empty($params['autoPpsmit']) ? '' : ', autoPpsmit: "'. $params['autoPpsmit']. '"').
243
+ (empty($params['responseType']) ? '' : ', responseType: "'. $params['responseType']. '"').
244
+ (empty($params['onChange']) ? '' : ', onChange: '. $params['onChange']. '').
245
+ (empty($params['onPpsmit']) ? '' : ', onPpsmit: '. $params['onPpsmit']. '').
246
+ (empty($params['onComplete']) ? '' : ', onComplete: '. $params['onComplete']. '').
247
+ '});
248
+ });
249
+ // --></script>';
250
+ return $out;
251
+ }
252
+ static public function button($params = array('attrs' => '', 'value' => '')) {
253
+ return '<button '. $params['attrs']. '>'. $params['value']. '</button>';
254
+ }
255
+ static public function buttonA($params = array('attrs' => '', 'value' => '')) {
256
+ return '<a href="#" '. $params['attrs']. '>'. $params['value']. '</a>';
257
+ }
258
+ static public function inputButton($params = array('attrs' => '', 'value' => '')) {
259
+ if(!is_array($params))
260
+ $params = array();
261
+ $params['type'] = 'button';
262
+ return self::input('', $params);
263
+ }
264
+ static public function radiobuttons($name, $params = array('attrs' => '', 'options' => array(), 'value' => '', '')) {
265
+ $out = '';
266
+ if(isset($params['options']) && is_array($params['options']) && !empty($params['options'])) {
267
+ $params['labeled'] = isset($params['labeled']) ? $params['labeled'] : false;
268
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
269
+ $params['no_br'] = isset($params['no_br']) ? $params['no_br'] : false;
270
+ foreach($params['options'] as $key => $val) {
271
+ /*$id = self::nameToClassId($key). '_'. mt_rand(1, 999999);
272
+ $attrs = $params['attrs'];
273
+ $attrs .= ' id="'. $id. '"';*/
274
+ $checked =($key == $params['value']) ? 'checked' : '';
275
+ if($params['labeled']) {
276
+ $out .= '<label>'. $val. '&nbsp;';
277
+ }
278
+ $out .= self::input($name, array('attrs' => $params['attrs'].' '.$checked, 'type' => 'radio', 'value' => $key));
279
+ if($params['labeled']) {
280
+ $out .= '</label>';
281
+ }
282
+ if(!$params['no_br']) {
283
+ $out .= '<br />';
284
+ }
285
+ }
286
+ }
287
+ return $out;
288
+ }
289
+ static public function radiobutton($name, $params = array('attrs' => '', 'value' => '', 'checked' => '')) {
290
+ $params['type'] = 'radio';
291
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
292
+ if(isset($params['checked']) && $params['checked'])
293
+ $params['attrs'] .= ' checked';
294
+ return self::input($name, $params);
295
+ }
296
+ static public function nonajaxautocompleate($name, $params = array('attrs' => '', 'options' => array())) {
297
+ if(empty($params['options'])) return false;
298
+ $out = '';
299
+ $jsArray = array();
300
+ $oneItem = '<div id="%%ID%%"><div class="ac_list_item"><input type="hidden" name="'.$name.'[]" value="%%ID%%" />%%VAL%%</div><div class="close" onclick="removeAcOpt(%%ID%%)"></div><div class="br"></div></div>';
301
+ $tID = $name. '_ac';
302
+ $out .= self::text($tID. '_ac', array('attrs' => 'id="'.$tID.'"'));
303
+ $out .= '<div id="'.$name.'_wraper">';
304
+ foreach($params['options'] as $opt) {
305
+ $jsArray[$opt['id']] = $opt['text'];
306
+ if(isset($opt['checked']) && $opt['checked'] == 'checked') {
307
+ $out .= str_replace(array('%%ID%%', '%%VAL%%'), array($opt['id'], $opt['text']), $oneItem);
308
+ }
309
+ }
310
+ $out .= '</div>';
311
+ $out .= '<script type="text/javascript">
312
+ var ac_values_'.$name.' = '.json_encode(array_values($jsArray)).';
313
+ var ac_keys_'.$name.' = '.json_encode(array_keys($jsArray)).';
314
+ jQuery(document).ready(function(){
315
+ jQuery("#'.$tID.'").autocomplete(ac_values_'.$name.', {
316
+ autoFill: false,
317
+ mustMatch: false,
318
+ matchContains: false
319
+ }).result(function(a, b, c){
320
+ var keyID = jQuery.inArray(c, ac_values_'.$name.');
321
+ if(keyID != -1) {
322
+ addAcOpt(ac_keys_'.$name.'[keyID], c, "'.$name.'");
323
+ }
324
+ });
325
+ });
326
+ </script>';
327
+ return $out;
328
+ }
329
+ static public function formStart($name, $params = array('action' => '', 'method' => 'GET', 'attrs' => '', 'hideMethodInside' => false)) {
330
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
331
+ $params['action'] = isset($params['action']) ? $params['action'] : '';
332
+ $params['method'] = isset($params['method']) ? $params['method'] : 'GET';
333
+ if(isset($params['hideMethodInside']) && $params['hideMethodInside']) {
334
+ return '<form name="'. $name. '" action="'. $params['action']. '" method="'. $params['method']. '" '. $params['attrs']. '>'.
335
+ self::hidden('method', array('value' => $params['method']));
336
+ } else {
337
+ return '<form name="'. $name. '" action="'. $params['action']. '" method="'. $params['method']. '" '. $params['attrs']. '>';
338
+ }
339
+ }
340
+ static public function formEnd() {
341
+ return '</form>';
342
+ }
343
+ static public function statesInput($name, $params = array('value' => '', 'attrs' => '', 'notSelected' => true, 'id' => '', 'selectHtml' => '')) {
344
+ if(empty($params['selectHtml']) || !method_exists(html, $params['selectHtml']))
345
+ return false;
346
+
347
+ $params['notSelected'] = isset($params['notSelected']) ? $params['notSelected'] : true;
348
+ $states = fieldAdapterPps::getStates($params['notSelected']);
349
+
350
+ foreach($states as $sid => $s) {
351
+ $params['options'][$sid] = $s['name'];
352
+ }
353
+ $idSelect = '';
354
+ $idText = '';
355
+ $id = '';
356
+ if(!empty($params['id'])) {
357
+ $id = $params['id'];
358
+ } else {
359
+ $id = self::nameToClassId($name);
360
+ }
361
+ $paramsText = $paramsSelect = $params;
362
+ $paramsText['attrs'] .= 'id = "'. $id. '_text"';
363
+ $paramsSelect['attrs'] .= 'id = "'. $id. '_select"';
364
+ $res = '';
365
+ $res .= self::$params['selectHtml']($name, $paramsSelect);
366
+ $res .= self::text($name, $paramsText);
367
+ if(empty($params['doNotAddJs'])) {
368
+ $res .= '<script type="text/javascript">
369
+ // <!--
370
+ if(!toeStates.length)
371
+ toeStates = '. utilsPps::jsonEncode($states). ';
372
+ toeStatesObjects["'. $id. '"] = new toeStatesSelect("'. $id. '");
373
+ // -->
374
+ </script>';
375
+ }
376
+ return $res;
377
+ }
378
+ static public function statesList($name, $params = array('value' => '', 'attrs' => '', 'notSelected' => true, 'id' => '')) {
379
+ $params['selectHtml'] = 'selectbox';
380
+ return self::statesInput($name, $params);
381
+ }
382
+ static public function statesListMultiple($name, $params = array('value' => '', 'attrs' => '', 'notSelected' => true, 'id' => '')) {
383
+ if(!empty($params['value'])) {
384
+ if(is_string($params['value'])) {
385
+ if(strpos($params['value'], ','))
386
+ $params['value'] = array_map('trim', explode(',', $params['value']));
387
+ else
388
+ $params['value'] = array(trim($params['value']));
389
+ }
390
+ }
391
+ $params['selectHtml'] = 'selectlist';
392
+ return self::statesInput($name, $params);
393
+ }
394
+ static public function countryList($name, $params = array('value' => '', 'attrs' => '', 'notSelected' => true)) {
395
+ $params['notSelected'] = isset($params['notSelected']) ? $params['notSelected'] : true;
396
+ $params['options'] = fieldAdapterPps::getCountries($params['notSelected']);
397
+ $params['attrs'] .= ' type="country"';
398
+ return self::selectbox($name, $params);
399
+ }
400
+ static public function countryListMultiple($name, $params = array('value' => '', 'attrs' => '', 'notSelected' => true)) {
401
+ if(!empty($params['value'])) {
402
+ if(is_string($params['value'])) {
403
+ if(strpos($params['value'], ','))
404
+ $params['value'] = array_map('trim', explode(',', $params['value']));
405
+ else
406
+ $params['value'] = array(trim($params['value']));
407
+ }
408
+ }
409
+ $params['notSelected'] = isset($params['notSelected']) ? $params['notSelected'] : true;
410
+ $params['options'] = fieldAdapterPps::getCountries($params['notSelected']);
411
+ $params['attrs'] .= ' type="country"';
412
+ return self::selectlist($name, $params);
413
+ }
414
+ static public function textFieldsDynamicTable($name, $params = array('value' => '', 'attrs' => '', 'options' => array())) {
415
+ $res = '';
416
+ if(empty($params['options']))
417
+ $params['options'] = array(0 => array('label' => ''));
418
+ if(!empty($params['options'])) {
419
+ $pattern = array();
420
+ foreach($params['options'] as $key => $p) {
421
+ $pattern[$key] = htmlPps::text($name. '[]['. $key. ']');
422
+ }
423
+ $countOptions = count($params['options']);
424
+ $remove = '<a href="#" onclick="toeRemoveTextFieldsDynamicTable(this); return false;">remove</a>';
425
+ $add = '<a href="#" onclick="toeAddTextFieldsDynamicTable(this, '. $countOptions. '); return false;">add</a>';
426
+
427
+ $res = '<div class="toeTextFieldsDynamicTable">';
428
+ if(empty($params['value']))
429
+ $params['value'] = array();
430
+ elseif(!is_array($params['value'])) {
431
+ $params['value'] = utilsPps::jsonDecode($params['value']);
432
+ //$params['value'] = $params['value'][0];
433
+ }
434
+ $i = 0;
435
+ do {
436
+ $res .= '<div class="toeTextFieldDynamicRow">';
437
+ foreach($params['options'] as $key => $p) {
438
+ switch($countOptions) {
439
+ case 1:
440
+ if(isset($params['value'][$i]))
441
+ $value = is_array($params['value'][$i]) ? $params['value'][$i][$key] : $params['value'][$i];
442
+ else
443
+ $value = '';
444
+ break;
445
+ case 2:
446
+ default:
447
+ $value = isset($params['value'][$i][$key]) ? $params['value'][$i][$key] : '';
448
+ break;
449
+ }
450
+ $paramsForText = array(
451
+ 'value' => $value,
452
+ );
453
+ $res .= __($p['label']). htmlPps::text($name. '['. $i. ']['. $key. ']', $paramsForText);
454
+ }
455
+ $res .= $remove. '</div>';
456
+ $i++;
457
+ } while($i < count($params['value']));
458
+ $res .= $add;
459
+ $res .= '</div>';
460
+ }
461
+ return $res;
462
+ }
463
+ static public function categorySelectlist($name, $params = array('attrs'=>'', 'size'=> 5, 'value' => '')) {
464
+ self::_loadCategoriesOptions();
465
+ if(self::$categoriesOptions) {
466
+ $params['options'] = self::$categoriesOptions;
467
+ return self::selectlist($name, $params);
468
+ }
469
+ return false;
470
+ }
471
+ static public function categorySelectbox($name, $params = array('attrs'=>'', 'size'=> 5, 'value' => '')) {
472
+ self::_loadCategoriesOptions();
473
+ if(!empty(self::$categoriesOptions)) {
474
+ $params['options'] = self::$categoriesOptions;
475
+ return self::selectbox($name, $params);
476
+ }
477
+ return false;
478
+ }
479
+ static public function productsSelectlist($name, $params = array('attrs'=>'', 'size'=> 5, 'value' => '')) {
480
+ self::_loadProductsOptions();
481
+ if(!empty(self::$productsOptions)) {
482
+ $params['options'] = self::$productsOptions;
483
+ return self::selectlist($name, $params);
484
+ }
485
+ return false;
486
+ }
487
+ static public function productsSelectbox($name, $params = array('attrs'=>'', 'size'=> 5, 'value' => '')) {
488
+ self::_loadProductsOptions();
489
+ if(!empty(self::$productsOptions)) {
490
+ $params['options'] = self::$productsOptions;
491
+ return self::selectbox($name, $params);
492
+ }
493
+ return false;
494
+ }
495
+ static protected function _loadCategoriesOptions() {
496
+ if(empty(self::$categoriesOptions)) {
497
+ $categories = framePps::_()->getModule('products')->getCategories();
498
+ if(!empty($categories)) {
499
+ foreach($categories as $c) {
500
+ self::$categoriesOptions[$c->term_taxonomy_id] = $c->cat_name;
501
+ }
502
+ }
503
+ }
504
+ }
505
+ static protected function _loadProductsOptions() {
506
+ if(empty(self::$productsOptions)) {
507
+ $products = framePps::_()->getModule('products')->getModel()->get(array('getFields' => 'post.ID, post.post_title'));
508
+ if(!empty($products)) {
509
+ foreach($products as $p) {
510
+ self::$productsOptions[$p['ID']] = $p['post_title'];
511
+ }
512
+ }
513
+ }
514
+ }
515
+ static public function slider($name, $params = array('value' => 0, 'min' => 0, 'max' => 0, 'step' => 1, 'slide' => '')) {
516
+ $id = self::nameToClassId($name, $params);
517
+ $paramsStr = '';
518
+ if(!isset($params['slide']) || (empty($params['slide']) && $params['slide'] !== false)) { //Can be set to false to ignore function onSlide event binding
519
+ $params['slide'] = 'toeSliderMove';
520
+ }
521
+ if(!empty($params)) {
522
+ $paramsArr = array();
523
+ foreach($params as $k => $v) {
524
+ if(in_array($k, array('attrs')) || strpos($k, '-')) continue;
525
+ $value = (is_numeric($v) || in_array($k, array('slide'))) ? $v : '"'. $v. '"';
526
+ $paramsArr[] = $k. ': '. $value;
527
+ }
528
+ $paramsStr = implode(', ', $paramsArr);
529
+ }
530
+
531
+ $res = '<div id="toeSliderDisplay_'. $id. '">'. (empty($params['value']) ? '' : $params['value']). '</div>';
532
+ $res .= '<div id="'. $id. '"></div>';
533
+ $params['attrs'] = 'id="toeSliderInput_'. $id. '"';
534
+ $res .= self::hidden($name, $params);
535
+ $res .= '<script type="text/javascript"><!--
536
+ jQuery(function(){
537
+ jQuery("#'. $id. '").slider({'. $paramsStr. '});
538
+ });
539
+ --></script>';
540
+ return $res;
541
+ }
542
+ static public function capcha() {
543
+ return recapchaPps::_()->getHtml();
544
+ }
545
+ static public function textIncDec($name, $params = array('value' => '', 'attrs' => '', 'options' => array(), 'onclick' => '', 'id' => '')) {
546
+ if(!isset($params['attrs']))
547
+ $params['attrs'] = '';
548
+ $textId = (isset($params['id']) && !empty($params['id'])) ? $params['id'] : 'toeTextIncDec_'. mt_rand(9, 9999);
549
+ $params['attrs'] .= ' id="'. $textId. '"';
550
+ $textField = self::text($name, $params);
551
+ $onClickInc = 'toeTextIncDec(\''. $textId. '\', 1); return false;';
552
+ $onClickDec = 'toeTextIncDec(\''. $textId. '\', -1); return false;';
553
+ if(isset($params['onclick']) && !empty($params['onclick'])) {
554
+ $onClickInc = $params['onclick']. ' '. $onClickInc;
555
+ $onClickDec = $params['onclick']. ' '. $onClickDec;
556
+ }
557
+ $textField .= '<div class="toeUpdateQtyButtonsWrapper"><div class="toeIncDecButton toeIncButton '. $textId. '" onclick="'. $onClickInc. '">+</div>'
558
+ . '<div class="toeIncDecButton toeDecButton '. $textId. '" onclick="'. $onClickDec. '">-</div></div>';
559
+ return $textField;
560
+ }
561
+ static public function colorpicker($name, $params = array('value' => '')) {
562
+ $params['value'] = isset($params['value']) ? $params['value'] : '';
563
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
564
+ $nameToClass = self::nameToClassId($name);
565
+ $textId = self::nameToClassId($name, $params);
566
+ if(strpos($params['attrs'], 'id="') === false) {
567
+ $textId .= '_'. mt_rand(9, 9999);
568
+ $params['attrs'] .= 'id="'. $textId. '"';
569
+ }
570
+ //$pickerId = $textId. '_picker';
571
+ $params['attrs'] .= ' data-default-color="'. $params['value']. '"';
572
+ $out = self::text($name, $params);
573
+ //$out .= '<div style="position: absolute; z-index: 1;" id="'. $pickerId. '"></div>';
574
+ $out .= '<script type="text/javascript">//<!--
575
+ jQuery(function(){
576
+ if(jQuery("#'. $textId. '").wpColorPicker) {
577
+ jQuery("#'. $textId. '").wpColorPicker({
578
+ change: function(event, ui) {
579
+ // Find change functiona for this element, if such exist - triger it
580
+ if(window["wpColorPicker_'. $nameToClass. '_change"]) {
581
+ window["wpColorPicker_'. $nameToClass. '_change"](event, ui);
582
+ }
583
+ }
584
+ });
585
+ } else {
586
+ var $colorInput = jQuery("<input type=\'color\' name=\'"+ jQuery("#'. $textId. '").attr("name")+ "\' />");
587
+ $colorInput.val( jQuery("#'. $textId. '").val() ).insertAfter( jQuery("#'. $textId. '") );
588
+ jQuery("#'. $textId. '").remove();
589
+ }
590
+ });
591
+ //--></script>';
592
+ return $out;
593
+ }
594
+ static public function fontsList($name, $params = array('value' => '')) {
595
+ static $options = array();
596
+
597
+ if(empty($options)) { // Fill them only one time per loading
598
+ foreach(fieldAdapterPps::getFontsList() as $font)
599
+ $options[ $font ] = $font;
600
+ }
601
+ $params['options'] = array();
602
+ if(isset($params['default'])) {
603
+ $params['options'] = array(PPS_DEFAULT => $params['default']);
604
+ }
605
+ $params['options'] = array_merge($params['options'], $options);
606
+ return self::selectbox($name, $params);
607
+ }
608
+ static public function checkboxHiddenVal($name, $params = array('attrs' => '', 'value' => '', 'checked' => '')) {
609
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
610
+ $checkId = self::nameToClassId($name, $params);
611
+ if(strpos($params['attrs'], 'id="') === false) {
612
+ $checkId .= '_check';
613
+ }
614
+ $hideId = self::nameToClassId($name, $params). '_text';
615
+ $paramsCheck = $paramsHidden = $params;
616
+ if(strpos($params['attrs'], 'id="') === false) {
617
+ $paramsCheck['attrs'] .= ' id="'. $checkId. '"';
618
+ }
619
+ $paramsCheck['attrs'] .= ' data-hideid="'. $hideId. '"';
620
+ $paramsHidden['attrs'] = ' id="'. $hideId. '"';
621
+ $paramsCheck['value'] = isset($paramsCheck['value']) ? $paramsCheck['value'] : '';
622
+ $paramsCheck['checked'] = $paramsCheck['value'] ? '1' : '0';
623
+ $out = self::checkbox(self::nameToClassId($name), $paramsCheck);
624
+ $out .= self::hidden($name, $paramsHidden);
625
+ $out .= '<script type="text/javascript">//<!--
626
+ jQuery(function(){
627
+ jQuery("#'. $checkId. '").change(function(){
628
+ jQuery("#'. $hideId. '").val( (jQuery(this).attr("checked") ? 1 : 0) );
629
+ });
630
+ });
631
+ //--></script>';
632
+ return $out;
633
+ }
634
+ static public function slideInput($name, $params = array('attrs' => '', 'checked' => false, 'id' => '')) {
635
+ $params = !isset($params) || empty($params) ? array() : $params;
636
+ if(!isset($params['id'])) {
637
+ $params['id'] = self::nameToClassId($name, $params);
638
+ if(strpos($params['attrs'], 'id="') === false) {
639
+ $params['id'] .= '_'. mt_rand(1, 99999);
640
+ }
641
+ }
642
+ $params['checked'] = isset($params['checked']) ? (int) $params['checked'] : 0;
643
+ $params['attrs'] = isset($params['attrs']) && !empty($params['attrs']) ? $params['attrs'] : '';
644
+ $params['attrs'] .= ' id="'. $params['id']. '"';
645
+
646
+ return '<a class="toeSlideShellPps" href="#"'. $params['attrs']. '>
647
+ <span class="toeSlideButtPps"></span>
648
+ <span class="toeSlideOnPps">'. __('ON'). '</span>
649
+ <span class="toeSlideOffPps">'. __('OFF'). '</span>
650
+ <input type="hidden" name="'. $name. '" />
651
+ </a>
652
+ <script type="text/javascript">
653
+ // <!--
654
+ jQuery(function(){
655
+ jQuery("#'. $params['id']. '").slideInput('. $params['checked']. ');
656
+ });
657
+ // -->
658
+ </script>';
659
+ }
660
+ static public function galleryBtn($name, $params = array()) {
661
+ $galleryType = isset($params['galleryType']) ? $params['galleryType'] : 'all';
662
+ $buttonId = self::nameToClassId($name, $params);
663
+ $params['value'] = isset($params['value']) ? $params['value'] : '';
664
+ $params['attrs'] = isset($params['attrs']) ? $params['attrs'] : '';
665
+ if(strpos($params['attrs'], 'id="') === false) {
666
+ $buttonId .= '_'. mt_rand(1, 99999);
667
+ $params['attrs'] .= ' id="'. $buttonId. '"';
668
+ }
669
+ $inputId = $buttonId. '_input';
670
+ $out = self::hidden($name, array('value' => $params['value'], 'attrs' => 'id="'. $inputId. '"'));
671
+ $onChange = isset($params['onChange']) ? $params['onChange'] : '';
672
+ $buttonParams = $params;
673
+ $buttonParams['value'] = isset($params['btnVal']) ? $params['btnVal'] : sprintf(__('Select %s', PPS_LANG_CODE), strFirstUp($galleryType));
674
+ $out .= self::buttonA($buttonParams);
675
+ $out .= '<script type="text/javascript">
676
+ // <!--
677
+ jQuery(function(){
678
+ // Run onChange to make pre-set of required data
679
+ '. ($onChange ? $onChange. '("'. $params['value']. '", null, "'. $buttonId. '");' : ''). '
680
+ jQuery("#'. $buttonId. '").click(function(){
681
+ var button = jQuery(this);
682
+ _custom_media = true;
683
+ wp.media.editor.send.attachment = function(props, attachment){
684
+ if ( _custom_media ) {
685
+ var selectedUrl = attachment.url;
686
+ if(props && props.size && attachment.sizes && attachment.sizes[ props.size ] && attachment.sizes[ props.size ].url) {
687
+ selectedUrl = attachment.sizes[ props.size ].url;
688
+ }
689
+ jQuery("#'. $inputId. '").val( selectedUrl ).trigger("change");
690
+ '. ($onChange ? $onChange. '(selectedUrl, attachment, "'. $buttonId. '");' : ''). '
691
+ } else {
692
+ return _orig_send_attachment.apply( this, [props, attachment] );
693
+ };
694
+ };
695
+ wp.media.editor.open(button);
696
+ jQuery(".attachment-filters").val("'. $galleryType. '").trigger("change");
697
+ return false;
698
+ });
699
+ });
700
+ // -->
701
+ </script>';
702
+ return $out;
703
+ }
704
+ static public function imgGalleryBtn($name, $params = array()) {
705
+ $params['galleryType'] = 'image';
706
+ return self::galleryBtn($name, $params);
707
+ }
708
+ static public function audioGalleryBtn($name, $params = array()) {
709
+ $params['galleryType'] = 'audio';
710
+ return self::galleryBtn($name, $params);
711
+ }
712
+ static public function checkedOpt($arr, $key, $value = true, $default = false) {
713
+ if(!isset($arr[ $key ])) {
714
+ return $default ? true : false;
715
+ }
716
+ return $value === true ? $arr[ $key ] : $arr[ $key ] == $value;
717
+ }
718
+ static public function nonceForAction( $action ) {
719
+ return self::hidden('_wpnonce', array('value' => wp_create_nonce(strtolower($action))));
720
+ }
721
+ }
classes/installer.php ADDED
@@ -0,0 +1,583 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class installerPps {
3
+ static public $update_to_version_method = '';
4
+ static private $_firstTimeActivated = false;
5
+ static public function init( $isUpdate = false ) {
6
+ global $wpdb;
7
+ $wpPrefix = $wpdb->prefix; /* add to 0.0.3 Versiom */
8
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
9
+ $current_version = get_option($wpPrefix. PPS_DB_PREF. 'db_version', 0);
10
+ if(!$current_version)
11
+ self::$_firstTimeActivated = true;
12
+ /**
13
+ * modules
14
+ */
15
+ if (!dbPps::exist("@__modules")) {
16
+ dbDelta(dbPps::prepareQuery("CREATE TABLE IF NOT EXISTS `@__modules` (
17
+ `id` smallint(3) NOT NULL AUTO_INCREMENT,
18
+ `code` varchar(32) NOT NULL,
19
+ `active` tinyint(1) NOT NULL DEFAULT '0',
20
+ `type_id` tinyint(1) NOT NULL DEFAULT '0',
21
+ `label` varchar(64) DEFAULT NULL,
22
+ `ex_plug_dir` varchar(255) DEFAULT NULL,
23
+ PRIMARY KEY (`id`),
24
+ UNIQUE INDEX `code` (`code`)
25
+ ) DEFAULT CHARSET=utf8;"));
26
+ dbPps::query("INSERT INTO `@__modules` (id, code, active, type_id, label) VALUES
27
+ (NULL, 'adminmenu',1,1,'Admin Menu'),
28
+ (NULL, 'options',1,1,'Options'),
29
+ (NULL, 'user',1,1,'Users'),
30
+ (NULL, 'pages',1,1,'Pages'),
31
+ (NULL, 'templates',1,1,'templates'),
32
+ (NULL, 'supsystic_promo',1,1,'supsystic_promo'),
33
+ (NULL, 'admin_nav',1,1,'admin_nav'),
34
+
35
+ (NULL, 'popup',1,1,'popup'),
36
+ (NULL, 'subscribe',1,1,'subscribe'),
37
+ (NULL, 'sm',1,1,'sm'),
38
+ (NULL, 'statistics',1,1,'statistics'),
39
+
40
+ (NULL, 'mail',1,1,'mail');");
41
+ }
42
+ /**
43
+ * modules_type
44
+ */
45
+ if(!dbPps::exist("@__modules_type")) {
46
+ dbDelta(dbPps::prepareQuery("CREATE TABLE IF NOT EXISTS `@__modules_type` (
47
+ `id` smallint(3) NOT NULL AUTO_INCREMENT,
48
+ `label` varchar(32) NOT NULL,
49
+ PRIMARY KEY (`id`)
50
+ ) AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;"));
51
+ dbPps::query("INSERT INTO `@__modules_type` VALUES
52
+ (1,'system'),
53
+ (6,'addons');");
54
+ }
55
+ /**
56
+ * Popup table
57
+ */
58
+ if (!dbPps::exist("@__popup")) {
59
+ dbDelta(dbPps::prepareQuery("CREATE TABLE IF NOT EXISTS `@__popup` (
60
+ `id` INT(11) NOT NULL AUTO_INCREMENT,
61
+ `label` VARCHAR(255) NOT NULL,
62
+ `active` TINYINT(1) NOT NULL,
63
+ `original_id` INT(11) NOT NULL DEFAULT '0',
64
+ `params` TEXT NOT NULL,
65
+ `html` TEXT NOT NULL,
66
+ `css` TEXT NOT NULL,
67
+ `img_preview` VARCHAR(128) NULL DEFAULT NULL,
68
+ `show_on` TINYINT(1) NOT NULL DEFAULT '0',
69
+ `show_to` TINYINT(1) NOT NULL DEFAULT '0',
70
+ `show_pages` TINYINT(1) NOT NULL DEFAULT '0',
71
+ `type_id` TINYINT(1) NOT NULL DEFAULT '1',
72
+
73
+ `views` INT(11) NOT NULL DEFAULT '0',
74
+ `unique_views` INT(11) NOT NULL DEFAULT '0',
75
+ `actions` INT(11) NOT NULL DEFAULT '0',
76
+
77
+ `date_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
78
+ PRIMARY KEY (`id`)
79
+ ) DEFAULT CHARSET=utf8;"));
80
+ }
81
+ if(!dbPps::exist("@__popup", "show_on")) {
82
+ dbPps::query("ALTER TABLE `@__popup` ADD COLUMN `show_on` TINYINT(1) NOT NULL DEFAULT '0';");
83
+ }
84
+ if(!dbPps::exist("@__popup", "views")) { // All those columns - were added in one update - so can place them in one condition - to not overload database
85
+ dbPps::query("ALTER TABLE `@__popup`
86
+ ADD COLUMN `views` INT(11) NOT NULL DEFAULT '0',
87
+ ADD COLUMN `unique_views` INT(11) NOT NULL DEFAULT '0',
88
+ ADD COLUMN `actions` INT(11) NOT NULL DEFAULT '0';");
89
+ }
90
+ if(!dbPps::exist("@__popup", "sort_order")) { // So, let's add some sorting here?;)
91
+ dbPps::query("ALTER TABLE `@__popup` ADD COLUMN `sort_order` MEDIUMINT(5) NOT NULL DEFAULT '0';");
92
+ }
93
+ if(!dbPps::exist("@__popup", "show_in_admin_area")) { // So, let's add some sorting here?;)
94
+ dbPps::query("ALTER TABLE `@__popup` ADD COLUMN `show_in_admin_area` TINYINT(1) NOT NULL DEFAULT '0';");
95
+ }
96
+ self::addAdditionalPopups();
97
+ self::makeTextFieldsCssUpdate();
98
+ self::makeTextFieldsCssUpdateRound2();
99
+ /**
100
+ * Popup ShowOn pages
101
+ */
102
+ if (!dbPps::exist("@__popup_show_pages")) {
103
+ dbDelta(dbPps::prepareQuery("CREATE TABLE `@__popup_show_pages` (
104
+ `popup_id` INT(10) NOT NULL,
105
+ `post_id` INT(10) NOT NULL,
106
+ `not_show` TINYINT(1) NOT NULL DEFAULT '0'
107
+ ) DEFAULT CHARSET=utf8;"));
108
+ }
109
+ /**
110
+ * Popup ShowOn categories (terms)
111
+ */
112
+ if (!dbPps::exist("@__popup_show_categories")) {
113
+ dbDelta(dbPps::prepareQuery("CREATE TABLE `@__popup_show_categories` (
114
+ `popup_id` INT(10) NOT NULL,
115
+ `term_id` INT(10) NOT NULL,
116
+ `not_show` TINYINT(1) NOT NULL DEFAULT '0'
117
+ ) DEFAULT CHARSET=utf8;"));
118
+ }
119
+ /**
120
+ * Plugin usage statistics
121
+ */
122
+ if(!dbPps::exist("@__usage_stat")) {
123
+ dbDelta(dbPps::prepareQuery("CREATE TABLE `@__usage_stat` (
124
+ `id` int(11) NOT NULL AUTO_INCREMENT,
125
+ `code` varchar(64) NOT NULL,
126
+ `visits` int(11) NOT NULL DEFAULT '0',
127
+ `spent_time` int(11) NOT NULL DEFAULT '0',
128
+ `modify_timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
129
+ UNIQUE INDEX `code` (`code`),
130
+ PRIMARY KEY (`id`)
131
+ ) DEFAULT CHARSET=utf8"));
132
+ dbPps::query("INSERT INTO `@__usage_stat` (code, visits) VALUES ('installed', 1)");
133
+ }
134
+ /**
135
+ * Statistics
136
+ */
137
+ if (!dbPps::exist("@__statistics")) {
138
+ dbDelta(dbPps::prepareQuery("CREATE TABLE `@__statistics` (
139
+ `id` int(11) NOT NULL AUTO_INCREMENT,
140
+ `popup_id` int(11) NOT NULL DEFAULT '0',
141
+ `type` TINYINT(2) NOT NULL DEFAULT '0',
142
+ `sm_id` TINYINT(2) NOT NULL DEFAULT '0',
143
+ `is_unique` TINYINT(1) NOT NULL DEFAULT '0',
144
+ `date_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
145
+ PRIMARY KEY (`id`)
146
+ ) DEFAULT CHARSET=utf8;"));
147
+ }
148
+ if(!dbPps::exist("@__statistics", "sm_id")) { // Social Media ID
149
+ dbPps::query("ALTER TABLE `@__statistics` ADD COLUMN `sm_id` TINYINT(2) NOT NULL DEFAULT '0';");
150
+ }
151
+ if(!dbPps::exist("@__statistics", "is_unique")) { // Unique
152
+ dbPps::query("ALTER TABLE `@__statistics` ADD COLUMN `is_unique` TINYINT(1) NOT NULL DEFAULT '0';");
153
+ }
154
+ /**
155
+ * Subscribers
156
+ */
157
+ if (!dbPps::exist("@__subscribers")) {
158
+ dbDelta(dbPps::prepareQuery("CREATE TABLE `@__subscribers` (
159
+ `id` int(11) NOT NULL AUTO_INCREMENT,
160
+ `username` VARCHAR(128) NULL DEFAULT NULL,
161
+ `email` VARCHAR(128) NOT NULL,
162
+ `hash` VARCHAR(128) NOT NULL,
163
+ `activated` TINYINT(1) NOT NULL DEFAULT '0',
164
+ `popup_id` int(11) NOT NULL DEFAULT '0',
165
+ `date_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
166
+ `all_data` TEXT NOT NULL,
167
+ PRIMARY KEY (`id`)
168
+ ) DEFAULT CHARSET=utf8;"));
169
+ }
170
+ if(!dbPps::exist("@__subscribers", "popup_id")) { // Popup ID for subscribers
171
+ dbPps::query("ALTER TABLE `@__subscribers` ADD COLUMN `popup_id` int(11) NOT NULL DEFAULT '0';");
172
+ }
173
+ if(!dbPps::exist("@__subscribers", "all_data")) { // All submit data for subscribers
174
+ dbPps::query("ALTER TABLE `@__subscribers` ADD COLUMN `all_data` TEXT NOT NULL;");
175
+ }
176
+ /**
177
+ * Countries
178
+ */
179
+ if (!dbPps::exist("@__countries")) {
180
+ dbDelta(dbPps::prepareQuery("CREATE TABLE `@__countries` (
181
+ `id` int(11) NOT NULL AUTO_INCREMENT,
182
+ `name` varchar(128) NOT NULL,
183
+ `iso_code_2` varchar(2) DEFAULT NULL,
184
+ `iso_code_3` varchar(3) DEFAULT NULL,
185
+ PRIMARY KEY (`id`)
186
+ ) DEFAULT CHARSET=utf8;"));
187
+ self::_insertCountries();
188
+ }
189
+ installerDbUpdaterPps::runUpdate();
190
+ if($current_version && !self::$_firstTimeActivated) {
191
+ self::setUsed();
192
+ // For users that just updated our plugin - don't need tp show step-by-step tutorial
193
+ update_user_meta(get_current_user_id(), PPS_CODE . '-tour-hst', array('closed' => 1));
194
+ }
195
+ update_option($wpPrefix. PPS_DB_PREF. 'db_version', PPS_VERSION);
196
+ add_option($wpPrefix. PPS_DB_PREF. 'db_installed', 1);
197
+ }
198
+ static public function setUsed() {
199
+ update_option(PPS_DB_PREF. 'plug_was_used', 1);
200
+ }
201
+ static public function isUsed() {
202
+ //return true; // No welcome page for now
203
+ //return 0;
204
+ return (int) get_option(PPS_DB_PREF. 'plug_was_used');
205
+ }
206
+ static public function delete() {
207
+ self::_checkSendStat('delete');
208
+ global $wpdb;
209
+ $wpPrefix = $wpdb->prefix;
210
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."modules`");
211
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."modules_type`");
212
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."usage_stat`");
213
+ //$wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."popup`");
214
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."popup_show_pages`");
215
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."statistics`");
216
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."statistics_sm`");
217
+ $wpdb->query("DROP TABLE IF EXISTS `".$wpPrefix.PPS_DB_PREF."subscribers`");
218
+ delete_option($wpPrefix. PPS_DB_PREF. 'db_version');
219
+ delete_option($wpPrefix. PPS_DB_PREF. 'db_installed');
220
+ }
221
+ static public function deactivate() {
222
+ self::_checkSendStat('deactivate');
223
+ }
224
+ static private function _checkSendStat($statCode) {
225
+ if(class_exists('framePps')
226
+ && framePps::_()->getModule('supsystic_promo')
227
+ && framePps::_()->getModule('options')
228
+ ) {
229
+ framePps::_()->getModule('supsystic_promo')->getModel()->saveUsageStat( $statCode );
230
+ framePps::_()->getModule('supsystic_promo')->getModel()->checkAndSend( true );
231
+ }
232
+ }
233
+ static public function update() {
234
+ global $wpdb;
235
+ $wpPrefix = $wpdb->prefix; /* add to 0.0.3 Versiom */
236
+ $currentVersion = get_option($wpPrefix. PPS_DB_PREF. 'db_version', 0);
237
+ if(!$currentVersion || version_compare(PPS_VERSION, $currentVersion, '>')) {
238
+ self::init( true );
239
+ update_option($wpPrefix. PPS_DB_PREF. 'db_version', PPS_VERSION);
240
+ }
241
+ }
242
+ static private function _insertCountries() {
243
+ dbPps::query('INSERT INTO @__countries VALUES
244
+ (1, "Afghanistan", "AF", "AFG"),
245
+ (2, "Albania", "AL", "ALB"),
246
+ (3, "Algeria", "DZ", "DZA"),
247
+ (4, "American Samoa", "AS", "ASM"),
248
+ (5, "Andorra", "AD", "AND"),
249
+ (6, "Angola", "AO", "AGO"),
250
+ (7, "Anguilla", "AI", "AIA"),
251
+ (8, "Antarctica", "AQ", "ATA"),
252
+ (9, "Antigua and Barbuda", "AG", "ATG"),
253
+ (10, "Argentina", "AR", "ARG"),
254
+ (11, "Armenia", "AM", "ARM"),
255
+ (12, "Aruba", "AW", "ABW"),
256
+ (13, "Australia", "AU", "AUS"),
257
+ (14, "Austria", "AT", "AUT"),
258
+ (15, "Azerbaijan", "AZ", "AZE"),
259
+ (16, "Bahamas", "BS", "BHS"),
260
+ (17, "Bahrain", "BH", "BHR"),
261
+ (18, "Bangladesh", "BD", "BGD"),
262
+ (19, "Barbados", "BB", "BRB"),
263
+ (20, "Belarus", "BY", "BLR"),
264
+ (21, "Belgium", "BE", "BEL"),
265
+ (22, "Belize", "BZ", "BLZ"),
266
+ (23, "Benin", "BJ", "BEN"),
267
+ (24, "Bermuda", "BM", "BMU"),
268
+ (25, "Bhutan", "BT", "BTN"),
269
+ (26, "Bolivia", "BO", "BOL"),
270
+ (27, "Bosnia and Herzegowina", "BA", "BIH"),
271
+ (28, "Botswana", "BW", "BWA"),
272
+ (29, "Bouvet Island", "BV", "BVT"),
273
+ (30, "Brazil", "BR", "BRA"),
274
+ (31, "British Indian Ocean Territory", "IO", "IOT"),
275
+ (32, "Brunei Darussalam", "BN", "BRN"),
276
+ (33, "Bulgaria", "BG", "BGR"),
277
+ (34, "Burkina Faso", "BF", "BFA"),
278
+ (35, "Burundi", "BI", "BDI"),
279
+ (36, "Cambodia", "KH", "KHM"),
280
+ (37, "Cameroon", "CM", "CMR"),
281
+ (38, "Canada", "CA", "CAN"),
282
+ (39, "Cape Verde", "CV", "CPV"),
283
+ (40, "Cayman Islands", "KY", "CYM"),
284
+ (41, "Central African Republic", "CF", "CAF"),
285
+ (42, "Chad", "TD", "TCD"),
286
+ (43, "Chile", "CL", "CHL"),
287
+ (44, "China", "CN", "CHN"),
288
+ (45, "Christmas Island", "CX", "CXR"),
289
+ (46, "Cocos (Keeling) Islands", "CC", "CCK"),
290
+ (47, "Colombia", "CO", "COL"),
291
+ (48, "Comoros", "KM", "COM"),
292
+ (49, "Congo", "CG", "COG"),
293
+ (50, "Cook Islands", "CK", "COK"),
294
+ (51, "Costa Rica", "CR", "CRI"),
295
+ (52, "Cote D\'Ivoire", "CI", "CIV"),
296
+ (53, "Croatia", "HR", "HRV"),
297
+ (54, "Cuba", "CU", "CUB"),
298
+ (55, "Cyprus", "CY", "CYP"),
299
+ (56, "Czech Republic", "CZ", "CZE"),
300
+ (57, "Denmark", "DK", "DNK"),
301
+ (58, "Djibouti", "DJ", "DJI"),
302
+ (59, "Dominica", "DM", "DMA"),
303
+ (60, "Dominican Republic", "DO", "DOM"),
304
+ (61, "East Timor", "TP", "TMP"),
305
+ (62, "Ecuador", "EC", "ECU"),
306
+ (63, "Egypt", "EG", "EGY"),
307
+ (64, "El Salvador", "SV", "SLV"),
308
+ (65, "Equatorial Guinea", "GQ", "GNQ"),
309
+ (66, "Eritrea", "ER", "ERI"),
310
+ (67, "Estonia", "EE", "EST"),
311
+ (68, "Ethiopia", "ET", "ETH"),
312
+ (69, "Falkland Islands (Malvinas)", "FK", "FLK"),
313
+ (70, "Faroe Islands", "FO", "FRO"),
314
+ (71, "Fiji", "FJ", "FJI"),
315
+ (72, "Finland", "FI", "FIN"),
316
+ (73, "France", "FR", "FRA"),
317
+ (74, "France, Metropolitan", "FX", "FXX"),
318
+ (75, "French Guiana", "GF", "GUF"),
319
+ (76, "French Polynesia", "PF", "PYF"),
320
+ (77, "French Southern Territories", "TF", "ATF"),
321
+ (78, "Gabon", "GA", "GAB"),
322
+ (79, "Gambia", "GM", "GMB"),
323
+ (80, "Georgia", "GE", "GEO"),
324
+ (81, "Germany", "DE", "DEU"),
325
+ (82, "Ghana", "GH", "GHA"),
326
+ (83, "Gibraltar", "GI", "GIB"),
327
+ (84, "Greece", "GR", "GRC"),
328
+ (85, "Greenland", "GL", "GRL"),
329
+ (86, "Grenada", "GD", "GRD"),
330
+ (87, "Guadeloupe", "GP", "GLP"),
331
+ (88, "Guam", "GU", "GUM"),
332
+ (89, "Guatemala", "GT", "GTM"),
333
+ (90, "Guinea", "GN", "GIN"),
334
+ (91, "Guinea-bissau", "GW", "GNB"),
335
+ (92, "Guyana", "GY", "GUY"),
336
+ (93, "Haiti", "HT", "HTI"),
337
+ (94, "Heard and Mc Donald Islands", "HM", "HMD"),
338
+ (95, "Honduras", "HN", "HND"),
339
+ (96, "Hong Kong", "HK", "HKG"),
340
+ (97, "Hungary", "HU", "HUN"),
341
+ (98, "Iceland", "IS", "ISL"),
342
+ (99, "India", "IN", "IND"),
343
+ (100, "Indonesia", "ID", "IDN"),
344
+ (101, "Iran (Islamic Republic of)", "IR", "IRN"),
345
+ (102, "Iraq", "IQ", "IRQ"),
346
+ (103, "Ireland", "IE", "IRL"),
347
+ (104, "Israel", "IL", "ISR"),
348
+ (105, "Italy", "IT", "ITA"),
349
+ (106, "Jamaica", "JM", "JAM"),
350
+ (107, "Japan", "JP", "JPN"),
351
+ (108, "Jordan", "JO", "JOR"),
352
+ (109, "Kazakhstan", "KZ", "KAZ"),
353
+ (110, "Kenya", "KE", "KEN"),
354
+ (111, "Kiribati", "KI", "KIR"),
355
+ (112, "Korea, Democratic People\'s Republic of", "KP", "PRK"),
356
+ (113, "Korea, Republic of", "KR", "KOR"),
357
+ (114, "Kuwait", "KW", "KWT"),
358
+ (115, "Kyrgyzstan", "KG", "KGZ"),
359
+ (116, "Lao People\'s Democratic Republic", "LA", "LAO"),
360
+ (117, "Latvia", "LV", "LVA"),
361
+ (118, "Lebanon", "LB", "LBN"),
362
+ (119, "Lesotho", "LS", "LSO"),
363
+ (120, "Liberia", "LR", "LBR"),
364
+ (121, "Libyan Arab Jamahiriya", "LY", "LBY"),
365
+ (122, "Liechtenstein", "LI", "LIE"),
366
+ (123, "Lithuania", "LT", "LTU"),
367
+ (124, "Luxembourg", "LU", "LUX"),
368
+ (125, "Macau", "MO", "MAC"),
369
+ (126, "Macedonia, The Former Yugoslav Republic of", "MK", "MKD"),
370
+ (127, "Madagascar", "MG", "MDG"),
371
+ (128, "Malawi", "MW", "MWI"),
372
+ (129, "Malaysia", "MY", "MYS"),
373
+ (130, "Maldives", "MV", "MDV"),
374
+ (131, "Mali", "ML", "MLI"),
375
+ (132, "Malta", "MT", "MLT"),
376
+ (133, "Marshall Islands", "MH", "MHL"),
377
+ (134, "Martinique", "MQ", "MTQ"),
378
+ (135, "Mauritania", "MR", "MRT"),
379
+ (136, "Mauritius", "MU", "MUS"),
380
+ (137, "Mayotte", "YT", "MYT"),
381
+ (138, "Mexico", "MX", "MEX"),
382
+ (139, "Micronesia, Federated States of", "FM", "FSM"),
383
+ (140, "Moldova, Republic of", "MD", "MDA"),
384
+ (141, "Monaco", "MC", "MCO"),
385
+ (142, "Mongolia", "MN", "MNG"),
386
+ (143, "Montenegro", "ME", "MNE"),
387
+ (144, "Montserrat", "MS", "MSR"),
388
+ (145, "Morocco", "MA", "MAR"),
389
+ (146, "Mozambique", "MZ", "MOZ"),
390
+ (147, "Myanmar", "MM", "MMR"),
391
+ (148, "Namibia", "NA", "NAM"),
392
+ (149, "Nauru", "NR", "NRU"),
393
+ (150, "Nepal", "NP", "NPL"),
394
+ (151, "Netherlands", "NL", "NLD"),
395
+ (152, "Netherlands Antilles", "AN", "ANT"),
396
+ (153, "New Caledonia", "NC", "NCL"),
397
+ (154, "New Zealand", "NZ", "NZL"),
398
+ (155, "Nicaragua", "NI", "NIC"),
399
+ (156, "Niger", "NE", "NER"),
400
+ (157, "Nigeria", "NG", "NGA"),
401
+ (158, "Niue", "NU", "NIU"),
402
+ (159, "Norfolk Island", "NF", "NFK"),
403
+ (160, "Northern Mariana Islands", "MP", "MNP"),
404
+ (161, "Norway", "NO", "NOR"),
405
+ (162, "Oman", "OM", "OMN"),
406
+ (163, "Pakistan", "PK", "PAK"),
407
+ (164, "Palau", "PW", "PLW"),
408
+ (165, "Panama", "PA", "PAN"),
409
+ (166, "Papua New Guinea", "PG", "PNG"),
410
+ (167, "Paraguay", "PY", "PRY"),
411
+ (168, "Peru", "PE", "PER"),
412
+ (169, "Philippines", "PH", "PHL"),
413
+ (170, "Pitcairn", "PN", "PCN"),
414
+ (171, "Poland", "PL", "POL"),
415
+ (172, "Portugal", "PT", "PRT"),
416
+ (173, "Puerto Rico", "PR", "PRI"),
417
+ (174, "Qatar", "QA", "QAT"),
418
+ (175, "Reunion", "RE", "REU"),
419
+ (176, "Romania", "RO", "ROM"),
420
+ (177, "Russian Federation", "RU", "RUS"),
421
+ (178, "Rwanda", "RW", "RWA"),
422
+ (179, "Saint Kitts and Nevis", "KN", "KNA"),
423
+ (180, "Saint Lucia", "LC", "LCA"),
424
+ (181, "Saint Vincent and the Grenadines", "VC", "VCT"),
425
+ (182, "Samoa", "WS", "WSM"),
426
+ (183, "San Marino", "SM", "SMR"),
427
+ (184, "Sao Tome and Principe", "ST", "STP"),
428
+ (185, "Saudi Arabia", "SA", "SAU"),
429
+ (186, "Senegal", "SN", "SEN"),
430
+ (187, "Serbia", "RS", "SRB"),
431
+ (188, "Seychelles", "SC", "SYC"),
432
+ (189, "Sierra Leone", "SL", "SLE"),
433
+ (190, "Singapore", "SG", "SGP"),
434
+ (191, "Slovakia (Slovak Republic)", "SK", "SVK"),
435
+ (192, "Slovenia", "SI", "SVN"),
436
+ (193, "Solomon Islands", "SB", "SLB"),
437
+ (194, "Somalia", "SO", "SOM"),
438
+ (195, "South Africa", "ZA", "ZAF"),
439
+ (196, "South Georgia and the South Sandwich Islands", "GS", "SGS"),
440
+ (197, "Spain", "ES", "ESP"),
441
+ (198, "Sri Lanka", "LK", "LKA"),
442
+ (199, "St. Helena", "SH", "SHN"),
443
+ (200, "St. Pierre and Miquelon", "PM", "SPM"),
444
+ (201, "Sudan", "SD", "SDN"),
445
+ (202, "Suriname", "SR", "SUR"),
446
+ (203, "Svalbard and Jan Mayen Islands", "SJ", "SJM"),
447
+ (204, "Swaziland", "SZ", "SWZ"),
448
+ (205, "Sweden", "SE", "SWE"),
449
+ (206, "Switzerland", "CH", "CHE"),
450
+ (207, "Syrian Arab Republic", "SY", "SYR"),
451
+ (208, "Taiwan", "TW", "TWN"),
452
+ (209, "Tajikistan", "TJ", "TJK"),
453
+ (210, "Tanzania, United Republic of", "TZ", "TZA"),
454
+ (211, "Thailand", "TH", "THA"),
455
+ (212, "Togo", "TG", "TGO"),
456
+ (213, "Tokelau", "TK", "TKL"),
457
+ (214, "Tonga", "TO", "TON"),
458
+ (215, "Trinidad and Tobago", "TT", "TTO"),
459
+ (216, "Tunisia", "TN", "TUN"),
460
+ (217, "Turkey", "TR", "TUR"),
461
+ (218, "Turkmenistan", "TM", "TKM"),
462
+ (219, "Turks and Caicos Islands", "TC", "TCA"),
463
+ (220, "Tuvalu", "TV", "TUV"),
464
+ (221, "Uganda", "UG", "UGA"),
465
+ (222, "Ukraine", "UA", "UKR"),
466
+ (223, "United Arab Emirates", "AE", "ARE"),
467
+ (224, "United Kingdom", "GB", "GBR"),
468
+ (225, "United States", "US", "USA"),
469
+ (226, "United States Minor Outlying Islands", "UM", "UMI"),
470
+ (227, "Uruguay", "UY", "URY"),
471
+ (228, "Uzbekistan", "UZ", "UZB"),
472
+ (229, "Vanuatu", "VU", "VUT"),
473
+ (230, "Vatican City State (Holy See)", "VA", "VAT"),
474
+ (231, "Venezuela", "VE", "VEN"),
475
+ (232, "Viet Nam", "VN", "VNM"),
476
+ (233, "Virgin Islands (British)", "VG", "VGB"),
477
+ (234, "Virgin Islands (U.S.)", "VI", "VIR"),
478
+ (235, "Wallis and Futuna Islands", "WF", "WLF"),
479
+ (236, "Western Sahara", "EH", "ESH"),
480
+ (237, "Yemen", "YE", "YEM"),
481
+ (238, "Zaire", "ZR", "ZAR"),
482
+ (239, "Zambia", "ZM", "ZMB"),
483
+ (240, "Zimbabwe", "ZW", "ZWE")');
484
+ }
485
+ static public function addAdditionalPopups() {
486
+ // Remember last increment value
487
+ $lastAutoIncrement = dbPps::getAutoIncrement('@__popup');
488
+ $lastAutoIncrement = $lastAutoIncrement && $lastAutoIncrement > 30 ? $lastAutoIncrement : 100;
489
+ $popupLastId = 39;
490
+ //dbPps::query('DELETE FROM @__popup WHERE id IN ('. implode(',', range(0, $popupLastId)). ')'); // We updated all popups as we did changes in all of them
491
+ if(!dbPps::exist('@__popup', 'id', '7')) { // First set of additional templates
492
+ dbPps::query('INSERT INTO @__popup (id,label,active,original_id,params,html,css,img_preview,show_on,show_to,show_pages,type_id,date_created,sort_order) VALUES
493
+ ("1","List Building","1","0","YTozOntzOjQ6Im1haW4iO2E6MTU6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjIxOiJoaWRlX2Zvcl9kZXZpY2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9mb3JfcG9zdF90eXBlc19zaG93IjtzOjE6IjAiO3M6MTc6ImhpZGVfZm9yX2lwc19zaG93IjtzOjE6IjAiO3M6MTI6ImhpZGVfZm9yX2lwcyI7czowOiIiO3M6MjM6ImhpZGVfZm9yX2NvdW50cmllc19zaG93IjtzOjE6IjAiO3M6MjM6ImhpZGVfZm9yX2xhbmd1YWdlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo1ODp7czo1OiJ3aWR0aCI7czozOiI4MjQiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZWJlYmViIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzA2NmRhYiI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiMwMGVhZWEiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiMwMDAwMDAiO3M6MTA6ImZvbnRfdHh0XzEiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzEiO3M6NzoiIzAwMDAwMCI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czo5OiJjbG9zZV9idG4iO3M6MTE6Imxpc3RzX2JsYWNrIjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjExOiJsYXllcmVkX3BvcyI7czowOiIiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MTQwOiJUaGUgQmVzdCBXb3JkUHJlc3MgPGkgc3R5bGU9XCJjb2xvcjogIzAwNjlhNztcIj5Qb3BVcCBvcHRpbiBwbHVnaW48L2k+IHRvIGhlbHAgeW91IGdhaW4gbW9yZSBzdWJzY3JpYmVycywgc29jaWFsIGZvbGxvd2VycyBvciBhZHZlcnRpc2VtZW50LiI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJlbmJfdHh0XzEiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTg6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSAiO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo2OiJzaW1wbGUiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjg6IlNpZ24tdXAhIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjU6InR4dF8wIjtzOjE2MDoiPHA+PGEgaHJlZj1cImh0dHA6Ly9zdXBzeXN0aWMuY29tXCIgdGFyZ2V0PVwiX2JsYW5rXCI+PGltZyBzdHlsZT1cIm1heC13aWR0aDogMjAwcHg7XCIgc3JjPVwiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvc3Vwc3lzdGljX2ljb24ucG5nXCIgYWx0PVwiXCIgLz48L2E+PC9wPiI7czo1OiJ0eHRfMSI7czozMTM6IjxwPlBvcHVwIGJ5IFN1cHN5c3RpYyBsZXRzIHlvdSBlYXNpbHkgY3JlYXRlIGVsZWdhbnQgb3ZlcmxhcHBpbmcgd2luZG93cyB3aXRoIHVubGltaXRlZCBmZWF0dXJlcy4gUG9wLXVwcyB3aXRoIFNsaWRlciwgTGlnaHRib3gsIENvbnRhY3QgYW5kIFN1YnNjcmlwdGlvbiBmb3JtcyBhbmQgbW9yZTo8L3A+PHVsPjxsaT5VbmxpbWl0ZWQgQ29udGVudCBDdXN0b21pemF0aW9uPC9saT48bGk+QXV0byBPcGVuIFBvcHVwczwvbGk+PGxpPkNvbnRhY3QgRm9ybSB3aXRoIHBvcC11cDwvbGk+PGxpPlBvcHVwIE9wZW5pbmcgQW5pbWF0aW9uczwvbGk+PC91bD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjMiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMiI7fX0=","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 66%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n vertical-align: top;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \"Myriad Pro\",\"Trebuchet MS\",\"Helvetica Neue\",Helvetica,Arial,Sans-Serif;\r\n font-size: 30px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n text-shadow: 0px 0px 1px #000;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n width: 34%;\r\n height: 100%;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 1px solid #d1b36d;\r\n border-radius: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background-color: #fff;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -5px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/mail-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 90% center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n background: -moz-linear-gradient(90deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -webkit-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -o-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -ms-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: linear-gradient(0deg, [bg_color_2]) 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 2px 2px 2px #000;\r\n cursor: pointer;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 50%;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n float: right;\r\n [if enb_txt_0]\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}","","1","1","1","1","2015-01-10 18:59:43","7"),
494
+ ("2","Classy","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU5OntzOjU6IndpZHRoIjtzOjM6IjYzMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNkMWQxZDEiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjN2ZiNmNiIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzU1NTU1NSI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjNTU1NTU1IjtzOjEwOiJmb250X3R4dF8xIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8xIjtzOjc6IiM1NTU1NTUiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM5OTk5OTkiO3M6OToiY2xvc2VfYnRuIjtzOjExOiJjbGFzc3lfZ3JleSI7czo3OiJidWxsZXRzIjtzOjExOiJjbGFzc3lfYmx1ZSI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fXM6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjg6IlNpZ24tVXAhIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MTg6IlBvcFVwIGJ5IFN1cHN5c3RpYyI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJlbmJfdHh0XzEiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MDoiIjtzOjU6InR4dF8wIjtzOjIwODoiPHA+UG9wdXAgYnkgU3Vwc3lzdGljIGxldHMgeW91IGVhc2lseSBjcmVhdGUgZWxlZ2FudCBvdmVybGFwcGluZyB3aW5kb3dzIHdpdGggdW5saW1pdGVkIGZlYXR1cmVzOjwvcD48dWw+PGxpPlVubGltaXRlZCBDb250ZW50IEN1c3RvbWl6YXRpb248L2xpPjxsaT5BdXRvIE9wZW4gUG9wdXBzPC9saT48bGk+Q29udGFjdCBGb3JtIHdpdGggcG9wLXVwPC9saT48L3VsPiI7czo1OiJ0eHRfMSI7czoxMjM6IjxwPjxpbWcgc3R5bGU9XCJtYXgtd2lkdGg6IDE4MHB4OyBtYXgtaGVpZ2h0OiBhdXRvO1wiIHNyYz1cIltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL3N1cHN5c3RpY19pY29uLnBuZ1wiIGFsdD1cIlwiIC8+PC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMiI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIyIjt9fQ==","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupClassyShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupClassyInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupClassyLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">[foot_note]</div>\r\n [endif]\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n [if bg_type_0 == \'color\']\r\n background-color: {{ popup.params.tpl.bg_color_0 }};\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-size: 100%;\r\n background-repeat: no-repeat;\r\n [endif]\r\n padding: 7px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClassyInner {\r\n padding: 15px;\r\n border: {{ adjust_brightness(popup.params.tpl.bg_color_0, 30) }};\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ popup.params.tpl.bg_color_0 }}), color-stop(100%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }})); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ popup.params.tpl.bg_color_0 }}\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }}\',GradientType=1 ); /* ie6-9 */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: 48px;\r\n font-size: 27px;\r\n border: none;\r\n padding: 1px 8px 0;\r\n width: calc((100% - 70px) / 3);\r\n box-sizing: content-box;\r\n margin-top: 10px;\r\n float: left;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n [if bg_type_0 == \'color\']\r\n -webkit-box-shadow: inset 4px 4px 4px 0px {{ adjust_brightness(popup.params.tpl.bg_color_0, -40) }};\r\n -moz-box-shadow: inset 4px 4px 4px 0px {{ adjust_brightness(popup.params.tpl.bg_color_0, -40) }};\r\n box-shadow: inset 4px 4px 4px 0px {{ adjust_brightness(popup.params.tpl.bg_color_0, -40) }};\r\n background-color: {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }};\r\n color: {{ adjust_brightness(popup.params.tpl.bg_color_0, -100) }};\r\n [endif]\r\n margin-right: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n height: 48px;\r\n vertical-align: middle;\r\n background-color: transparent;\r\n border: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select option {\r\n font-size: 27px;\r\n color: #6d6d6d;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: calc(100% - 30px);\r\n height: auto;\r\n font-family: inherit;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n color: #eee;\r\n margin-right: 0;\r\n cursor: pointer;\r\n [if bg_type_1 == \'color\']\r\n text-shadow: -1px -1px 1px {{ adjust_brightness(popup.params.tpl.bg_color_1, -80) }};\r\n border: 1px solid {{ adjust_brightness(popup.params.tpl.bg_color_1, -40) }};\r\n background: -moz-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ popup.params.tpl.bg_color_1 }}), color-stop(100%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }})); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ popup.params.tpl.bg_color_1 }}\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }}\',GradientType=1 ); /* ie6-9 */\r\n\r\n -webkit-box-shadow: inset 0px 0px 2px 2px {{ adjust_brightness(popup.params.tpl.bg_color_1, 10) }};\r\n -moz-box-shadow: inset 0px 0px 2px 2px {{ adjust_brightness(popup.params.tpl.bg_color_1, 10) }};\r\n box-shadow: inset 0px 0px 2px 2px {{ adjust_brightness(popup.params.tpl.bg_color_1, 10) }};\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-size: 100%;\r\n background-repeat: no-repeat;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:disabled {\r\n color: transparent;\r\n cursor: progress;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n margin: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClassyLabel {\r\n width: 100%;\r\n text-align: center;\r\n color: #555555;\r\n text-shadow: 1px 1px 1px #ffffff;\r\n font-size: 35px;\r\n margin-top: 26px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSuccessMsg {\r\n color: #555555;\r\n border: 1px solid #555555;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt {\r\n font-size: 20px;\r\n line-height: 160%;\r\n color: rgb(85, 85, 85);\r\n padding-top: 14px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n [if enb_txt_1]\r\n width: 70%;\r\n float: left;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n float: right;\r\n width: 30%;\r\n}\r\n#ppsPopupShell_[ID] ul {\r\n margin-top: 15px;\r\n padding-left: 0;\r\n}\r\n#ppsPopupShell_[ID] ul li {\r\n list-style: inside none disc;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #999;\r\n font-size: 12px;\r\n padding-top: 10px;\r\n text-align: center;\r\n}\r\n/*SM*/\r\n#ppsPopupShell_[ID] .ppsSm {\r\n padding: 10px 10px 0 10px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_1_435376 .ppsSm > div {\r\n vertical-align: top !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm .ppsSmBtn {\r\n margin-right: 5px;\r\n}","","1","1","1","1","2015-01-03 17:00:43","19"),
495
+ ("3","Fastest and the Easiest","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjYzOntzOjU6IndpZHRoIjtzOjM6Ijc3MCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNlNWU1ZTUiO3M6OToiYmdfdHlwZV8xIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMSI7czozOToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvYnV0dG9uLTEucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjA6IiI7czo5OiJiZ190eXBlXzIiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18yIjtzOjQyOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9iaWctYXJyb3ctMS5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzQxNDE0MSI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjEwOiJmb250X3R4dF8xIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8xIjtzOjc6IiMwMDAwMDAiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM5Nzk2OTYiO3M6OToiY2xvc2VfYnRuIjtzOjExOiJsaXN0c19ibGFjayI7czo3OiJidWxsZXRzIjtzOjExOiJsaXN0c19ncmVlbiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fXM6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjU6IkpvaW4hIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6NTU6IkluY3JlYXNlIHN1YnNjcmliZXJzLCBzb2NpYWwgZm9sbG93ZXJzIG9yIGFkdmVydGlzZW1lbnQiO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZW5iX3R4dF8xIjtzOjE6IjEiO3M6MTM6ImVuYl9mb290X25vdGUiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE3OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUiO3M6NToidHh0XzAiO3M6NDQ6IjxwPlRoZSBCZXN0IFdvcmRQcmVzcyBQb3BVcCBvcHRpbiBwbHVnaW48L3A+IjtzOjU6InR4dF8xIjtzOjMxMzoiPHA+UG9wdXAgYnkgU3Vwc3lzdGljIGxldHMgeW91IGVhc2lseSBjcmVhdGUgZWxlZ2FudCBvdmVybGFwcGluZyB3aW5kb3dzIHdpdGggdW5saW1pdGVkIGZlYXR1cmVzLiBQb3AtdXBzIHdpdGggU2xpZGVyLCBMaWdodGJveCwgQ29udGFjdCBhbmQgU3Vic2NyaXB0aW9uIGZvcm1zIGFuZCBtb3JlOjwvcD48dWw+PGxpPlVubGltaXRlZCBDb250ZW50IEN1c3RvbWl6YXRpb248L2xpPjxsaT5BdXRvIE9wZW4gUG9wdXBzPC9saT48bGk+Q29udGFjdCBGb3JtIHdpdGggcG9wLXVwPC9saT48bGk+UG9wdXAgT3BlbmluZyBBbmltYXRpb25zPC9saT48L3VsPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMyI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIyIjt9fQ==","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupListsInner\">\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_0\">\r\n <div class=\"ppsTxtContent\">[txt_0]</div>\r\n </div>\r\n [endif]\r\n <div class=\"ppsPopupTblCols\">\r\n <div class=\"ppsPopupLeftCol\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_1\">[txt_1]</div>\r\n [endif]\r\n </div>\r\n <div class=\"ppsPopupRightCol\">\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n <div class=\"ppsBigArrow\"></div>\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n \r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: Helvetica,Arial,sans-serif;\r\n font-size: 14px;\r\n \r\n [if bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #414141;\r\n font-size: 28px;\r\n font-style: normal;\r\n font-weight: bold;\r\n letter-spacing: -1px;\r\n line-height: 35px;\r\n text-shadow: 0 1px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupListsInner {\r\n [if bg_type_0 == \'color\']\r\n background: {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}; /* Old browsers */\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* FF3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%,[bg_color_0])); /* Chrome,Safari4+ */\r\n background: -webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Opera 12+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* IE10+ */\r\n background: radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'#eaeaea\',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n width: 100%;\r\n border-bottom: 1px solid {{ adjust_brightness(popup.params.tpl.bg_color_0, -50) }};\r\n clear: both;\r\n font-size: 13px;\r\n font-weight: bold;\r\n font-family: Helvetica,Arial,sans-serif;\r\n [if bg_type_0 == \'color\']\r\n background: [bg_color_0]; /* Old browsers */\r\n background: -moz-linear-gradient(top, [bg_color_0] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }} 100%); /* FF3.6+ */\r\n background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,[bg_color_0]), color-stop(100%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }})); /* Chrome,Safari4+ */\r\n background: -webkit-linear-gradient(top, [bg_color_0] 0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }} 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-linear-gradient(top, [bg_color_0] 0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }} 100%); /* Opera 11.10+ */\r\n background: -ms-linear-gradient(top, [bg_color_0] 0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }} 100%); /* IE10+ */\r\n background: linear-gradient(to bottom, [bg_color_0] 0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }} 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'[bg_color_0]\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 20) }}\',GradientType=0 ); /* IE6-9 */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 .ppsTxtContent {\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTblCols {\r\n display: table;\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLeftCol {\r\n display: table-cell;\r\n vertical-align: top;\r\n [if enb_subscribe]\r\n width: 64%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupRightCol {\r\n width: 36%;\r\n display: table-cell;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 1px solid #000;\r\n border-radius: 10px;\r\n display: block;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n vertical-align: middle;\r\n height: 40px;\r\n background-color: transparent;\r\n border: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n margin-left: -10px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: auto;\r\n font-family: inherit;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/mail-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 90% center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: none;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n background: -moz-linear-gradient(90deg, [bg_color_1] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 100) }} 63%);\r\n background: -webkit-linear-gradient(270deg, [bg_color_1] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 100) }} 63%);\r\n background: -o-linear-gradient(270deg, [bg_color_1] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 100) }} 63%);\r\n background: -ms-linear-gradient(270deg, [bg_color_1] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 100) }} 63%);\r\n background: linear-gradient(0deg, [bg_color_1]) 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 100) }} 63%);\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #000;\r\n font-size: 20px;\r\n text-shadow: 2px 2px 2px #000;\r\n cursor: pointer;\r\n max-width: 230px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #979696;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsBigArrow {\r\n [if bg_type_2 == \'img\']\r\n position: absolute;\r\n width: 102px;\r\n height: 81px;\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n top: -20px;\r\n right: 20px;\r\n z-index: 100;\r\n [else]\r\n display: none;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSuccessMsg {\r\n padding: 55px 5px 5px;\r\n}","","1","1","1","1","2015-01-13 19:22:48","13"),
496
+ ("4","Facebook Like","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjIwOntzOjU6IndpZHRoIjtzOjM6IjMwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czo2OiJoZWlnaHQiO3M6MDoiIjtzOjE0OiJoZWlnaHRfbWVhc3VyZSI7czoyOiJweCI7czoxMjoiZmJfbGlrZV9vcHRzIjthOjM6e3M6NDoiaHJlZiI7czo1NzoiaHR0cHM6Ly93d3cuZmFjZWJvb2suY29tL3BhZ2VzL1N1cHN5c3RpYy8xMzg5MzkwMTk4MDI4OTk5IjtzOjQ6InRhYnMiO2E6MTp7aTowO3M6ODoidGltZWxpbmUiO31zOjEzOiJzaG93X2ZhY2VwaWxlIjtzOjE6IjEiO31zOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjE1OiJiZ19vdmVybGF5X3R5cGUiO3M6NToiY29sb3IiO3M6MTY6ImJnX292ZXJsYXlfY29sb3IiO3M6NDoiIzAwMCI7czoxNDoiYmdfb3ZlcmxheV9pbWciO3M6MDoiIjtzOjE4OiJiZ19vdmVybGF5X2ltZ19wb3MiO3M6Nzoic3RyZXRjaCI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6ImNsYXNzeV9ncmV5IjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czoxOiIxIjtzOjEyOiJzdGF0X2dhX2NvZGUiO3M6MDoiIjt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIxIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjAiO319","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupFbLikeShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n [fb_like_widget_html]\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n /*height: [height][height_measure];*/\r\n [if bg_type_0 == \'color\']\r\n background-color: [bg_color_0];\r\n [elseif bg_type_0 == \'img\']\r\n background-repeat: no_repeat;\r\n background-image: url(\"[bg_img_0]\");\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n z-index: 99;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n","","1","1","1","2","2015-01-16 19:35:51","3"),
497
+ ("5","Video List","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU2OntzOjk6InZpZGVvX3VybCI7czo0MzoiaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1uS0l1OXllbjVuYyI7czo1OiJ3aWR0aCI7czozOiI4MjQiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6NjoiaGVpZ2h0IjtzOjM6IjQwMCI7czoxNDoiaGVpZ2h0X21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18wIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZWJlYmViIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzA2NmRhYiI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiM4NTAwMDgiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjNTg1ODU4IjtzOjk6ImNsb3NlX2J0biI7czoxMToibGlzdHNfYmxhY2siO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO31zOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjU6ImxhYmVsIjtzOjU5OiJDaGVjayB2aWRlbyBhbmQgPGkgc3R5bGU9XCJjb2xvcjogI2MyMjUyZjtcIj5zdWJzY3JpYmUhPC9pPiI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTg6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSAiO31zOjEwOiJvcHRzX2F0dHJzIjthOjM6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjMiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMCI7czoyMToidmlkZW9faGVpZ2h0X2FzX3BvcHVwIjtzOjE6IjEiO319","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n <div style=\"clear: both;\"></div>\r\n [endif]\r\n <div class=\"ppsPopupVideo \">\r\n [video_html]\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] iframe {\r\n width: 100% !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 66%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \"Myriad Pro\",\"Trebuchet MS\",\"Helvetica Neue\",Helvetica,Arial,Sans-Serif;\r\n font-size: 30px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n text-shadow: 0px 0px 1px #000;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n width: 34%;\r\n height: 100%;\r\n vertical-align: top;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 1px solid #d1b36d;\r\n border-radius: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background-color: #fff;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -5px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/mail-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 90% center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n background: -moz-linear-gradient(90deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -webkit-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -o-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -ms-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: linear-gradient(0deg, [bg_color_2]) 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 2px 2px 2px #000;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupVideo {\r\n width: 100%;\r\n line-height: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}","","1","1","1","3","2015-01-10 18:59:43","17"),
498
+ ("6","Video Classy","1","0","YTozOntzOjQ6Im1haW4iO2E6MjQ6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6NzE6e3M6OToidmlkZW9fdXJsIjtzOjQzOiJodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PW5LSXU5eWVuNW5jIjtzOjU6IndpZHRoIjtzOjM6IjYzMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czo2OiJoZWlnaHQiO3M6MzoiNDgwIjtzOjE0OiJoZWlnaHRfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNlY2UwZDEiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjN2ZiNmNiIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzU1NTU1NSI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzk5OTk5OSI7czo5OiJjbG9zZV9idG4iO3M6MTE6ImNsYXNzeV9ncmV5IjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6NToibGFiZWwiO3M6MTg6Ikxvb2sgb3VyIG5ldyB2aWRlbyI7czo5OiJmb290X25vdGUiO3M6MDoiIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fXM6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLVVwISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjU6IkxvZ2luIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6Mjc6IlRoYW5rIHlvdSBmb3IgcmVnaXN0cmF0aW9uISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHJlZ2lzdHJhdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTY6IllvdSByZWdpc3RlcmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHJlZ2lzdHJhdGlvbi4gSWYgeW91IGRpZCBub3QgcmVnaXN0ZXIgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxMjE6IllvdSBoYXZlIG5ldyBtZW1iZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBtZW1iZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO31zOjEwOiJvcHRzX2F0dHJzIjthOjQ6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjIiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMCI7czoyMDoidmlkZW9fd2lkdGhfYXNfcG9wdXAiO3M6MToiMSI7czoyMToidmlkZW9faGVpZ2h0X2FzX3BvcHVwIjtzOjE6IjEiO319","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupClassyShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupClassyInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupClassyLabel\">[label]</div>\r\n [endif]\r\n <div class=\"ppsPopupVideo\">\r\n [video_html]\r\n </div>\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">[foot_note]</div>\r\n [endif]\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n [if bg_type_0 == \'color\']\r\n background-color: {{ popup.params.tpl.bg_color_0 }};\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-size: 100%;\r\n background-repeat: no-repeat;\r\n [endif]\r\n padding: 7px;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClassyInner {\r\n padding: 0;\r\n border: {{ adjust_brightness(popup.params.tpl.bg_color_0, 30) }};\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ popup.params.tpl.bg_color_0 }}), color-stop(100%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }})); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ popup.params.tpl.bg_color_0 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }} 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ popup.params.tpl.bg_color_0 }}\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }}\',GradientType=1 ); /* ie6-9 */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n height: 48px;\r\n font-size: 27px;\r\n border: none;\r\n padding: 1px 8px 0;\r\n width: calc((100% - 70px) / 3);\r\n box-sizing: content-box;\r\n margin-top: 10px;\r\n float: left;\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n [if bg_type_0 == \'color\']\r\n -webkit-box-shadow: inset 4px 4px 4px 0px {{ adjust_brightness(popup.params.tpl.bg_color_0, -40) }};\r\n -moz-box-shadow: inset 4px 4px 4px 0px {{ adjust_brightness(popup.params.tpl.bg_color_0, -40) }};\r\n box-shadow: inset 4px 4px 4px 0px {{ adjust_brightness(popup.params.tpl.bg_color_0, -40) }};\r\n background-color: {{ adjust_brightness(popup.params.tpl.bg_color_0, -20) }};\r\n color: {{ adjust_brightness(popup.params.tpl.bg_color_0, -100) }};\r\n [endif]\r\n margin-right: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n height: 48px;\r\n vertical-align: middle;\r\n background-color: transparent;\r\n border: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select option {\r\n font-size: 27px;\r\n color: #6d6d6d;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: calc(100% - 30px);\r\n height: auto;\r\n font-family: inherit;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n color: #eee;\r\n margin-right: 0;\r\n cursor: pointer;\r\n [if bg_type_1 == \'color\']\r\n text-shadow: -1px -1px 1px {{ adjust_brightness(popup.params.tpl.bg_color_1, -80) }};\r\n border: 1px solid {{ adjust_brightness(popup.params.tpl.bg_color_1, -40) }};\r\n background: -moz-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ popup.params.tpl.bg_color_1 }}), color-stop(100%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }})); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ popup.params.tpl.bg_color_1 }} 0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }} 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ popup.params.tpl.bg_color_1 }}\', endColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, -50) }}\',GradientType=1 ); /* ie6-9 */\r\n\r\n -webkit-box-shadow: inset 0px 0px 2px 2px {{ adjust_brightness(popup.params.tpl.bg_color_1, 10) }};\r\n -moz-box-shadow: inset 0px 0px 2px 2px {{ adjust_brightness(popup.params.tpl.bg_color_1, 10) }};\r\n box-shadow: inset 0px 0px 2px 2px {{ adjust_brightness(popup.params.tpl.bg_color_1, 10) }};\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-size: 100%;\r\n background-repeat: no-repeat;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:disabled {\r\n color: transparent;\r\n cursor: progress;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n padding-top: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n margin: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClassyLabel {\r\n width: 100%;\r\n text-align: center;\r\n color: #555555;\r\n text-shadow: 1px 1px 1px #ffffff;\r\n font-size: 35px;\r\n margin-top: 26px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSuccessMsg {\r\n color: #555555;\r\n border: 1px solid #555555;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClassyTxt {\r\n font-size: 20px;\r\n line-height: 160%;\r\n color: rgb(85, 85, 85);\r\n padding-top: 14px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupVideo {\r\n width: 100%;\r\n line-height: 0;\r\n padding: 0;\r\n margin: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupVideo iframe {\r\n margin: 0;\r\n}\r\n#ppsPopupShell_[ID] ul {\r\n margin-top: 15px;\r\n padding-left: 0;\r\n}\r\n#ppsPopupShell_[ID] ul li {\r\n list-style: inside none disc;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n color: #999;\r\n font-size: 12px;\r\n padding-top: 10px;\r\n text-align: center;\r\n}\r\n/*SM*/\r\n#ppsPopupShell_[ID] .ppsSm {\r\n padding: 10px 10px 0 10px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_1_435376 .ppsSm > div {\r\n vertical-align: top !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm .ppsSmBtn {\r\n margin-right: 5px;\r\n}","","1","1","1","3","2015-01-03 17:00:43","16"),
499
+ ("7","Layered Popup","1","0","YTozOntzOjQ6Im1haW4iO2E6MjE6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjt9czozOiJ0cGwiO2E6ODA6e3M6NToid2lkdGgiO3M6MzoiNDAwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2YwNjIyZSI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNkYWQyYmYiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMiI7czo3OiIjNTU1NTU1IjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmZmZmZiI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjZmZmZmZmIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjNTg1ODU4IjtzOjE1OiJyZXNwb25zaXZlX21vZGUiO3M6MzoiZGVmIjtzOjk6ImNsb3NlX2J0biI7czoxMToid2hpbGVfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czoxODoiVGhlIEJlc3QgV29yZFByZXNzIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjEzOiJlbmJfZm9vdF9ub3RlIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExODoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czo2OiJlbmJfc20iO3M6MToiMSI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czozOiI1MDAiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjU6IkxvZ2luIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6Mjc6IlRoYW5rIHlvdSBmb3IgcmVnaXN0cmF0aW9uISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHJlZ2lzdHJhdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTY6IllvdSByZWdpc3RlcmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHJlZ2lzdHJhdGlvbi4gSWYgeW91IGRpZCBub3QgcmVnaXN0ZXIgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxMjE6IllvdSBoYXZlIG5ldyBtZW1iZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBtZW1iZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6NToidHh0XzAiO3M6MTcyOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmU8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIzIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #FFF;\r\n font-family: \"Myriad Pro\",\"Trebuchet MS\",\"Helvetica Neue\",Helvetica,Arial,Sans-Serif;\r\n font-size: 30px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n text-align: center;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n height: 100%;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 10% 15% 0;\r\n text-align:center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 1px solid #d1b36d;\r\n color: #888;\r\n text-shadow: 1px 1px 5px #888;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n font-size: 17px;\r\n width:100%;\r\n background-color: #fff;\r\n padding-left: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #888;\r\n text-shadow: 1px 1px 5px #888;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/mail-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 90% center;\r\n width:100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n width: 60%;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n box-shadow: -4px -4px 0px rgba(0, 0, 0, 0.1) inset;\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 1px 1px 1px #000;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 80%;\r\n margin-left: 10%;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n float: right;\r\n [if enb_txt_0]\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top:15px;\r\n right:10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\nmargin-top:20px;\r\n}","layered-popup.jpg","1","1","1","1","2015-01-10 18:59:43","1"),
500
+ ("9","SIGN UP","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6ODg6e3M6NToid2lkdGgiO3M6MzoiNDAwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiIzhjNzc2NCI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiM3NTM2MmMiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmOWU2Y2UiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6IndoaWxlX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MzA6IlNJR04gVVA8YnI+IHRvIG91ciBOZXdzbGV0dGVyISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6NzoiU0lHTiBVUCI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo4OiJsb2dpbl9ieSI7czo4OiJ1c2VybmFtZSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjU6IkxvZ2luIjtzOjIzOiJyZWdfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxMzoicmVnX2J0bl9sYWJlbCI7czo4OiJSZWdpc3RlciI7czoxMDoicmVnX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czoyNzoiVGhhbmsgeW91IGZvciByZWdpc3RyYXRpb24hIjtzOjIxOiJyZWdfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InJlZ19yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHJlZ2lzdHJhdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTY6IllvdSByZWdpc3RlcmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHJlZ2lzdHJhdGlvbi4gSWYgeW91IGRpZCBub3QgcmVnaXN0ZXIgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxMjE6IllvdSBoYXZlIG5ldyBtZW1iZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBtZW1iZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6NToidHh0XzAiO3M6MTcyOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmU8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIyIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Amatic+SC\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \'arial\', arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #f9e6ce;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n box-shadow: rgba(192,192,192,1) 0 4px 20px, 6px -6px 0px rgba(0, 0, 0, 0.1) inset;\r\n border-radius: 4px;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #FFF;\r\n font-family: \'Amatic SC\', arial;\r\n font-size: 45px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 10% 10% 5% 5%;\r\n text-align:right;\r\n margin-bottom: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n /*width: 100%;*/\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 0px solid #d1b36d;\r\n border-radius: 4px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 20px;\r\n font-size: 17px;\r\n width:100%;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -4px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/email-icon.png\");\r\n background-repeat: no-repeat;\r\n width:100%;\r\n background-attachment: scroll;\r\n background-position: 0px center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n width: 60%;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n box-shadow: -4px -4px 0px rgba(0, 0, 0, 0.1) inset;\r\n background-image: none;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 1px 1px 1px #000;\r\n cursor: pointer;\r\n padding: 0 6px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 80%;\r\n margin-left: 10%;\r\n text-align: justify;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n top:15px;\r\n right:10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] input[name=\"name\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/user-icon.png\");\r\n background-repeat: no-repeat;\r\n background-attachment: scroll;\r\n background-position: 0px center;\r\n}","sing-up.jpg","1","1","1","1","2015-01-10 18:59:43","3"),
501
+ ("10","Informed","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6ODg6e3M6NToid2lkdGgiO3M6MzoiNDAwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2NjY2NjYyI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZjAwMDAiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiMwMDAwMDAiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6OToic3FyX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MTI6IkJlIGluZm9ybWVkISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO31zOjQ6Im5hbWUiO2E6Njp7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6Mzoi4oiaIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6NToiTG9naW4iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJyZWdfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToicmVnX3R4dF9zdWNjZXNzIjtzOjI3OiJUaGFuayB5b3UgZm9yIHJlZ2lzdHJhdGlvbiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gcmVnaXN0cmF0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NjoiWW91IHJlZ2lzdGVyZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgcmVnaXN0cmF0aW9uLiBJZiB5b3UgZGlkIG5vdCByZWdpc3RlciBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjEzOiJyZWdfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToicmVnX25ld19tZXNzYWdlIjtzOjEyMToiWW91IGhhdmUgbmV3IG1lbWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIG1lbWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo1OiJ0eHRfMCI7czoxNzI6IjxwPlBvcHVwIGJ5IFN1cHN5c3RpYyBsZXRzIHlvdSBlYXNpbHkgY3JlYXRlIGVsZWdhbnQgb3ZlcmxhcHBpbmcgd2luZG93cyB3aXRoIHVubGltaXRlZCBmZWF0dXJlcy4gUG9wLXVwcyB3aXRoIFNsaWRlciwgTGlnaHRib3gsIENvbnRhY3QgYW5kIFN1YnNjcmlwdGlvbiBmb3JtcyBhbmQgbW9yZTwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjIiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Amatic+SC\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \'arial\', arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n border-radius: 4px;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n padding: 10px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n text-align: center;\r\n font-size: 45px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 1% 1% 1% 1%;\r\n text-align:right;\r\n margin-bottom: 20px;\r\n padding-left: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n /*width: 100%;*/\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 0px solid #d1b36d;\r\n border-radius: 4px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 20px;\r\n font-size: 17px;\r\n width: 100%;\r\n max-width: 284px;\r\n display: block;\r\n float: left;\r\n border: 1px solid #000;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n border-top-right-radius: 4px;\r\n border-bottom-right-radius: 4px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n width:75%;\r\n background-attachment: scroll;\r\n background-position: 0px center;\r\n border: 1px solid #000;\r\n display:block;\r\n float:left;\r\n padding-left:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n width: 15%;\r\n display:block;\r\n float: left;\r\n margin-left: 10px;\r\n padding: 10px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n box-shadow: -4px -4px 0px rgba(0, 0, 0, 0.1) inset;\r\n background-image: none;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 1px 1px 1px #000;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 80%;\r\n margin-left: 10%;\r\n text-align: center;\r\n color: black;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg{\r\n clear: both;\r\n text-align: left;\r\n}\r\n\r\n\r\n\r\n","informed.jpg","1","1","1","1","2015-01-10 18:59:43","5"),
502
+ ("11","START popup","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6OTY6e3M6NToid2lkdGgiO3M6MzoiODI0IjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNkYTk3MzIiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMiI7czo3OiIjNTQ4ZDJjIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzU2OTEyZCI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjODg4ODg4IjtzOjEwOiJmb250X3R4dF8xIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6IndoaWxlX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTI6ImNpcmNsZV9ncmVlbiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjI1OiJEbyB5b3Ugd2FudCBtb3JlIHRyYWZmaWM/IjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjk6ImVuYl90eHRfMSI7czoxOiIxIjtzOjEzOiJlbmJfZm9vdF9ub3RlIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjQ3OiIqIHdlIG5ldmVyIHNoYXJlIHlvdXIgZS1tYWlsIHdpdGggdGhpcmQgcGFydGllcyI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6MTM6IlNVQlNDUklCRSBOT1ciO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czo1OiJMb2dpbiI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6Mjc6IlRoYW5rIHlvdSBmb3IgcmVnaXN0cmF0aW9uISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSByZWdpc3RyYXRpb24gb24gW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk2OiJZb3UgcmVnaXN0ZXJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciByZWdpc3RyYXRpb24uIElmIHlvdSBkaWQgbm90IHJlZ2lzdGVyIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MTM6InJlZ19uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJyZWdfbmV3X21lc3NhZ2UiO3M6MTIxOiJZb3UgaGF2ZSBuZXcgbWVtYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgbWVtYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjU6InR4dF8wIjtzOjM4NjoiPHA+UG9wdXAgYnkgU3Vwc3lzdGljIGxldHMgeW91IGVhc2lseSBjcmVhdGUgZWxlZ2FudCBvdmVybGFwcGluZyB3aW5kb3dzIHdpdGggdW5saW1pdGVkIGZlYXR1cmVzLiBQb3AtdXBzIHdpdGggU2xpZGVyLCBMaWdodGJveCwgQ29udGFjdCBhbmQgU3Vic2NyaXB0aW9uIGZvcm1zIGFuZCBtb3JlOjwvcD48dWw+PGxpPlVubGltaXRlZCBDb250ZW50IEN1c3RvbWl6YXRpb248L2xpPjxsaT5BdXRvIE9wZW4gUG9wdXBzPC9saT48bGk+Q29udGFjdCBGb3JtIHdpdGggcG9wLXVwPC9saT48bGk+UG9wdXAgT3BlbmluZyBBbmltYXRpb25zPC9saT48bGk+VW5saW1pdGVkIENvbnRlbnQgQ3VzdG9taXphdGlvbjwvbGk+PGxpPlBvcHVwIE9wZW5pbmcgQW5pbWF0aW9uczwvbGk+PC91bD4iO3M6NToidHh0XzEiO3M6NzM6IjxwPlNVQlNDUklCRSBUTyBPVVIgTkVXU0xFVFRFUiBBTkQgU1RBUlQgSU5DUkVBU0lORyBZT1VSIFBST0ZJVFMgTk9XITwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjMiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMiI7fX0=","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 60%;\r\n box-shadow: rgba(32,32,32,1) 0 4px 20px;\r\n border-radius:3px;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: block;\r\n float: left;\r\n margin-top: 30px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #56912d;\r\n font-family: \'arial\', arial;\r\n font-size: 30px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n margin-top: 15px;\r\n padding-left: 20px;\r\n text-shadow: 0px 0px 1px #56912d;\r\n -moz-text-shadow: 0px 0px 1px #56912d;\r\n -webkit-text-shadow: 0px 0px 1px #56912d;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n border-radius:3px;\r\n width: 40%;\r\n height: 110%;\r\n display: block;\r\n float: right;\r\n box-shadow: rgba(32,32,32,1) 0 4px 20px;\r\n padding: 10px 0;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 1px solid #d1b36d;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 22px;\r\n font-size: 17px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/user-black-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n border-radius: 2px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/email-black-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n border-radius: 2px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n background-image: none;\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 2px 2px 2px #000;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 100%;\r\n color: #888888;\r\n font-family: \'arial\', arial;\r\n font-weight: 400;\r\n line-height: 1.3;\r\n font-size: 14px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 , #ppsPopupShell_[ID] .ppsPopupTxt_1 * {\r\n color:#ffffff;\r\n font-family: \'arial\', arial;\r\n font-weight: 700;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 25px;\r\n padding: 0 10px;\r\n margin: 0;\r\n letter-spacing: -1px;\r\n text-align: center;\r\n line-height: 1.475;\r\n [if enb_txt_0]\r\n width: 95;\r\n [else]\r\n width: 95%;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top:-20px;\r\n right:1px;\r\n z-index:99999;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n\r\n#ppsPopupShell_[ID] p{\r\n margin-left:20px;\r\n}\r\n#ppsPopupShell_[ID] b{\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] ul li {\r\n height:30px;\r\n}\r\n#ppsPopupShell_[ID] ul {\r\n margin: 14px 0;\r\n padding: 0 0 0 40px;\r\n}","start-popup.jpg","1","1","1","1","2015-01-10 18:59:43","26"),
503
+ ("12","Nature","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoxMDoic2hvd19wYWdlcyI7czozOiJhbGwiO3M6MTQ6InNob3dfdGltZV9mcm9tIjtzOjc6IjEyOjAwYW0iO3M6MTI6InNob3dfdGltZV90byI7czo3OiIxMjowMGFtIjtzOjE0OiJzaG93X2RhdGVfZnJvbSI7czowOiIiO3M6MTI6InNob3dfZGF0ZV90byI7czowOiIiO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoxNToiY291bnRfdGltZXNfbnVtIjtzOjE6IjEiO3M6MTU6ImNvdW50X3RpbWVzX21lcyI7czozOiJkYXkiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7czoyNDoiaGlkZV9zZWFyY2hfZW5naW5lc19zaG93IjtzOjE6IjAiO3M6MTg6ImhpZGVfcHJlZ191cmxfc2hvdyI7czoxOiIwIjtzOjEzOiJoaWRlX3ByZWdfdXJsIjtzOjA6IiI7czoyNDoiaGlkZV9mb3JfdXNlcl9yb2xlc19zaG93IjtzOjE6IjAiO31zOjM6InRwbCI7YTo1NTp7czo1OiJ3aWR0aCI7czozOiI2NzAiO3M6MTM6IndpZHRoX21lYXN1cmUiO3M6MjoicHgiO3M6MTg6ImJnX292ZXJsYXlfb3BhY2l0eSI7czozOiIwLjUiO3M6OToiYmdfdHlwZV8wIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMCI7czozNzoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvbmF0dXJlLmpwZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjMjMyMzIzIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzgxZDc0MiI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZmZmZmYiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzU4NTg1OCI7czoxNToicmVzcG9uc2l2ZV9tb2RlIjtzOjM6ImRlZiI7czoxNzoicmVpZHJlY3Rfb25fY2xvc2UiO3M6MDoiIjtzOjk6ImNsb3NlX2J0biI7czoxMToid2hpbGVfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjA6IiI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czoyMzoiU1VCU0NSSUJFIFRPIE5FV1NMRVRURVIiO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExODoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfc3ViamVjdCI7czo0MDoiTmV3IFN1YnNjcmliZXIgb24gTXkgV29yZFByZXNzIFRlc3QgU2l0ZSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjU6InR4dF8wIjtzOjE4OToiPHA+VHVycGlzIGRpcyBhbWV0IGFkaXBpc2NpbmcgaGFjIG1vbnRlcyBvZGlvIGFjIHZlbGl0PyBQb3J0YSwgbm9uIHJob25jdXMgdnV0LCB2ZWwsIGV0IGFkaXBpc2NpbmcgbWFnbmEgcHVsdmluYXIgYWRpcGlzY2luZyBlc3QgYWRpcGlzY2luZyB1cm5hLiBEaWduaXNzaW0gcmhvbmN1cyBzY2VsZXJpc3F1ZSBwdWx2aW5hcj88L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIyIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"label-window\">\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .label-window{\r\n background-color: rgba(10,10,10,0.6);\r\n width: 70%;\r\n padding-top: 10px;\r\n padding-bottom: 10px;\r\n margin-top: 20px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-size: 28px;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n float:right;\r\n width: 50%;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-top: 65px;\r\n [if bg_type_1 == \'color\']\r\n background-color: rgba(0,0,0,0.7);\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n text-align: right;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n background-color: rgba(0,0,0,0.8) !important;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n border-top-right-radius: 3px;\r\n border-bottom-right-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select option {\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n width: 60%;\r\n text-shadow: #000000 1px 1px 1px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n background: -moz-linear-gradient(90deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -webkit-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -o-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -ms-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: linear-gradient(0deg, [bg_color_2]) 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n \r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 14px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin: 20px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}","nature.png","1","1","1","1","2015-01-10 18:59:43","21"),
504
+ ("13","Ready","1","0","YTozOntzOjQ6Im1haW4iO2E6MjE6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjt9czozOiJ0cGwiO2E6Nzg6e3M6NToid2lkdGgiO3M6MzoiNTAwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czozOiJpbWciO3M6ODoiYmdfaW1nXzAiO3M6MzY6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL3JlYWR5LmpwZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjMjMyMzIzIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiI2ZmNDMwMCI7czo5OiJiZ190eXBlXzIiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzIiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiNmZjQzMDAiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiNmZmZmZmYiO3M6OToiY2xvc2VfYnRuIjtzOjExOiJ3aGlsZV9jbG9zZSI7czo3OiJidWxsZXRzIjtzOjExOiJjbGFzc3lfYmx1ZSI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjI2OiJBUkUgWU9VIFJFQURZPyBHRVQgSVQgTk9XISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czo1ODoiWW91ciBJbmZvcm1hdGlvbiB3aWxsIG5ldmVyIGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo4OiJ0aW5fZG93biI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjU6IkxvZ2luIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6Mjc6IlRoYW5rIHlvdSBmb3IgcmVnaXN0cmF0aW9uISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHJlZ2lzdHJhdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTY6IllvdSByZWdpc3RlcmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHJlZ2lzdHJhdGlvbi4gSWYgeW91IGRpZCBub3QgcmVnaXN0ZXIgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxMjE6IllvdSBoYXZlIG5ldyBtZW1iZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBtZW1iZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6NToidHh0XzAiO3M6NTI6IjxwPkluY3JlYXNlIG1vcmUgdGhhbiA3MDAlIG9mIEVtYWlsIFN1YnNjcmliZXJzITwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjMiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <div id=\"close\"><a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a></div>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_label]\r\n <div class=\"label-window\">\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\"><h2>[label]</h2></div>\r\n </div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .label-window{\r\n padding-top: 10px;\r\n padding-bottom: 10px;\r\n margin-top: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel,\r\n#ppsPopupShell_[ID] h2 {\r\n font-family: Open Sans, Arial, Tahoma, sans-serif;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-size: 18px;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n text-align: center;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 5%;\r\n padding-right: 5%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel h2:after{\r\n margin-top: 50px;\r\n position: absolute;\r\n left: 25%;\r\n right: 25%;\r\n height: 4px;\r\n background: [bg_color_1];\r\n content: \' \';\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n height: 100%;\r\n margin-top: 35%;\r\n [if bg_type_1 == \'color\']\r\n background: rgba(48, 20, 28, 0.7);\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n background-color: transparent;\r\n padding: 0 0 0 10px;\r\n font-size: 17px;\r\n border: 1px solid [bg_color_1];\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select option {\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n width: 50%;\r\n text-shadow: #000000 1px 1px 1px;\r\n padding: 0;\r\n float: none;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n \r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n -webkit-transition: all 0.2s ease-in-out;\r\n -moz-transition: all 0.2s ease-in-out;\r\n -ms-transition: all 0.2s ease-in-out;\r\n -o-transition: all 0.2s ease-in-out;\r\n \r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n background:#fff;\r\n color: [bg_color_1];\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 14px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin: 20px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: 15px;\r\n background: [bg_color_2];\r\n background-repeat: round;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #fff;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n text-align: center;\r\n}\r\n\r\n#ppsPopupShell_[ID]{\r\n color:[bg_color_1];\r\n}","ready.png","1","1","1","1","2015-01-10 18:59:43","2"),
505
+ ("14","Innovation","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU5OntzOjU6IndpZHRoIjtzOjM6IjY2MCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MzY6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL3JlYWR5LmpwZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjMjIyMjIyIjtzOjk6ImJnX3R5cGVfMSI7czozOiJpbWciO3M6ODoiYmdfaW1nXzEiO3M6NDE6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2lubm92YXRpb24ucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZjAwMDAiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMiI7czo3OiIjZmYwMDAwIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmZmZmZiI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjZmZmZmZmIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjk6ImNsb3NlX2J0biI7czo5OiJyZWRfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czoxNDoiU3Vic2NyaWJlIE5vdyEiO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo2OiJzaW1wbGUiO3M6ODoiYW5pbV9rZXkiO3M6ODoidGluX2Rvd24iO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MjY6IkFSRSBZT1UgUkVBRFk/IEdFVCBJVCBOT1chIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjEzOiJlbmJfZm9vdF9ub3RlIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjU4OiJZb3VyIEluZm9ybWF0aW9uIHdpbGwgbmV2ZXIgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IjtzOjU6InR4dF8wIjtzOjI0MjoiPGgzPkluY3JlYXNlIG1vcmUgdGhhbiA3MDAlIG9mIEVtYWlsIFN1YnNjcmliZXJzITwvaDM+PHA+PGJyIC8+TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gRHVpcyB2aXZlcnJhPGJyIC8+IHVybmEgdml0YWUgdmVoaWN1bGEgY29uZ3VlLCBwdXJ1cyBuaWJoIHZlc3RpYnVsdW0gbGFjdXMsIHNpdCBhbWV0IHRyaXN0aXF1ZSBhbnRlIG9kaW8gdml2ZXJyYSBvcmNpLjwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjMiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <div id=\"close\"><a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a></div>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"label-window\">\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n </div>\r\n [endif]\r\n <div class=\"header\">\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n </div>\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background:[bg_color_0]; /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .label-window{\r\n padding-top: 10px;\r\n padding-bottom: 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: Open Sans, Arial, Tahoma, sans-serif;\r\n font-size: 24px;\r\n font-weight: 900;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n text-align: center;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 5%;\r\n padding-right: 5%;\r\n \r\n}\r\n\r\n#ppsPopupShell_[ID] .header{\r\n width: 100%;\r\n height: 80px;\r\n [if bg_type_1 == \'color\']\r\n background:[bg_color_1]; \r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n height: 100%;\r\n [if bg_type_2 == \'color\']\r\n background:[bg_color_2]; \r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 25px;\r\n height: 40px;\r\n border: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 10px;\r\n font-size: 17px;\r\n border: 1px solid transparent;\r\n color: #959595;\r\n border-radius: 50px;\r\n box-sizing: border-box;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #959595;\r\n margin-left: -20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding: 5px 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n border-radius: 50px;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 800;\r\n font-size:16px;\r\n color: #ffffff;\r\n width: 35%;\r\n height: 45px;\r\n text-shadow: #000000 1px 1px 1px;\r\n background: transparent;\r\n -webkit-transition: all 0.5s ease-in-out;\r\n -moz-transition: all 0.5s ease-in-out;\r\n -ms-transition: all 0.5s ease-in-out;\r\n -o-transition: all 0.5s ease-in-out;\r\n border: 4px solid #fff;\r\n text-transform: uppercase;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n background:[bg_color_0];\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 14px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin: 20px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: 15px;\r\n}\r\n\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #fff;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n text-align: center;\r\n}","innovation.png","1","1","1","1","2015-01-10 18:59:43","25"),
506
+ ("15","Bonus","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6OTY6e3M6NToid2lkdGgiO3M6MzoiNzcwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2U1ZTVlNSI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6Mzk6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2J1dHRvbi0xLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjZmY0NDExIjtzOjk6ImJnX3R5cGVfMiI7czozOiJpbWciO3M6ODoiYmdfaW1nXzIiO3M6MzY6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2JvbnVzLnBuZyI7czoxMDoiYmdfY29sb3JfMiI7czowOiIiO3M6OToiYmdfdHlwZV8zIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18zIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjM2QzZDNkIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiI2ZmNDQxMSI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjOTc5Njk2IjtzOjE1OiJyZXNwb25zaXZlX21vZGUiO3M6MzoiZGVmIjtzOjE3OiJyZWlkcmVjdF9vbl9jbG9zZSI7czowOiIiO3M6OToiY2xvc2VfYnRuIjtzOjExOiJjbGFzc3lfZ3JleSI7czo3OiJidWxsZXRzIjtzOjQ6InRpY2siO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czo1NzoiR2V0IGl0IE5PVyEgSW5jcmVhc2UgbW9yZSB0aGFuIDcwMCUgb2YgRW1haWwgU3Vic2NyaWJlcnMhIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjEzOiJlbmJfZm9vdF9ub3RlIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExNzoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lIjtzOjY6ImVuYl9zbSI7czoxOiIxIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MjU6InN1Yl9tYWlsY2hpbXBfZ3JvdXBzX2Z1bGwiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTY6InN1Yl9ncl9jeWNsZV9kYXkiO3M6MToiMCI7czoxMzoic3ViX2ljX2FwcF9pZCI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfdXNlciI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfcGFzcyI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMzoic3ViX3NmX2FwcF9pZCI7czowOiIiO3M6MTQ6InN1Yl9ja19hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX21lbV9hY2NfaWQiO3M6MDoiIjtzOjE1OiJzdWJfbWVtX3B1ZF9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfbWVtX3ByaXZfa2V5IjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo5OiJTdWJzY3JpYmUiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6ODoibG9naW5fYnkiO3M6ODoidXNlcm5hbWUiO3M6MTg6ImxvZ2luX3JlZGlyZWN0X3VybCI7czowOiIiO3M6MTU6ImxvZ2luX2J0bl9sYWJlbCI7czo1OiJMb2dpbiI7czoyMzoicmVnX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTM6InJlZ19idG5fbGFiZWwiO3M6ODoiUmVnaXN0ZXIiO3M6MTA6InJlZ19maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InJlZ190eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJyZWdfdHh0X3N1Y2Nlc3MiO3M6Mjc6IlRoYW5rIHlvdSBmb3IgcmVnaXN0cmF0aW9uISI7czoyMToicmVnX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJyZWdfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSByZWdpc3RyYXRpb24gb24gW3NpdGVuYW1lXSI7czoyNToicmVnX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk2OiJZb3UgcmVnaXN0ZXJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciByZWdpc3RyYXRpb24uIElmIHlvdSBkaWQgbm90IHJlZ2lzdGVyIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MTM6InJlZ19uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJyZWdfbmV3X21lc3NhZ2UiO3M6MTIxOiJZb3UgaGF2ZSBuZXcgbWVtYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgbWVtYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjU6InR4dF8wIjtzOjQzMzoiPHA+Qm9udXMgUG9wdXAgaXQgaXMgdGhlIG1vc3QgcG93ZXJmdWwgcG9wdXAgc3lzdGVtIGZvciBXb3JkUHJlc3Mgb24gdGhlIG1hcmtldC4gSXQgY29tYmluZXMgYSBwcm9mZXNzaW9uYWxseSBkZXNpZ25lZCB3ZWxjb21lL2V4aXQgd2luZG93IHNvY2lhbCBsb2NrZXIgYW5kIHN1YnNjcmliaW5nIG9wdC1pbiBzeXN0ZW0gZm9yIHNtYXJ0IGUtbWFpbCBtYXJrZXRpbmcuPC9wPjx1bD48bGk+V2VsY29tZSwgZXhpdCBwb3B1cCB3aW5kb3c8L2xpPjxsaT5Tb2NpYWwgbmV0d29yayBzaGFyaW5nIGxvY2tlcjwvbGk+PGxpPlNtYXJ0IG5ld3NsZXR0ZXIgb3B0LWluIHN5c3RlbTwvbGk+PGxpPkZ1bGwgcG9wdXAgd2luZG93IGN1c3RvbWl6aW5nPC9saT48bGk+UGFnZSBsZXZlbCBUYXJnZXRpbmc8L2xpPjxsaT5NYW55IGxheW91dHMgdG8gY2hvb3NlPC9saT48L3VsPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNCI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupListsInner\">\r\n <div class=\"ppsPopupTblCols\">\r\n <div class=\"ppsPopupLeftCol\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_0\">[txt_0]</div>\r\n [endif]\r\n </div>\r\n <div class=\"ppsPopupRightCol\">\r\n <div class=\"ppsBigArrow\"></div>\r\n [if bg_type_2 == \'img\']\r\n <img src=\"[bg_img_2]\" />\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: Helvetica,Arial,sans-serif;\r\n font-size: 14px;\r\n [if bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: [bg_color_1];\r\n font-size: 25px;\r\n font-weight: bold;\r\n line-height: 1.2;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupListsInner {\r\n border: 3px solid #bac0ac;\r\n border-radius: 8px;\r\n -webkit-border-radius: 8px;\r\n -moz-border-radius: 8px;\r\n -webkit-box-shadow: inset 0 0 0 5px #fff, 0 10px 25px rgba(0,0,0,0.5);\r\n -moz-box-shadow: inset 0 0 0 5px #fff, 0 10px 25px rgba(0,0,0,0.5);\r\n box-shadow: inset 0 0 0 5px #fff, 0 10px 25px rgba(0,0,0,0.5);\r\n [if bg_type_0 == \'color\']\r\n background: {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}; /* Old browsers */\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* FF3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%,[bg_color_0])); /* Chrome,Safari4+ */\r\n background: -webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Opera 12+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* IE10+ */\r\n background: radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'#eaeaea\',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 .ppsTxtContent {\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTblCols {\r\n display: table;\r\n padding: 10px 10px 10px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLeftCol {\r\n display: table-cell;\r\n [if enb_subscribe]\r\n width: 60%;\r\n [else]\r\n width: 60%;\r\n min-height: 60%;\r\n [endif]\r\n vertical-align: top;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupRightCol {\r\n width: 36%;\r\n display: table-cell;\r\n border: 3px solid [bg_color_1];\r\n border-radius: 8px;\r\n -moz-border-radius: 8px;\r\n -webkit-border-radius: 8px;\r\n margin: 8px 5px 5px 5px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 20px 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 35px;\r\n border-radius: 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 0px [bg_color_1] inset;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background: [bg_color_1];\r\n border: 1px solid transparent;\r\n color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n margin-left: -15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding: 20px 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: none;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n background-image: none;\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n width: auto;\r\n padding: 5px 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n right: -5px;\r\n top: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n [if enb_subscribe]\r\n color: #979696;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [else]\r\n margin-top: 10px;\r\n color: #979696;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n[if enb_subscribe]\r\n [else]\r\n margin-top: 130px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] li{\r\n font-weight: bold;\r\n font-size: 13px;\r\n padding-top: 3px;\r\n padding-bottom: 3px;\r\n color: #737E86;\r\n}","bonus.png","1","1","1","1","2015-01-13 19:22:48","20"),
507
+ ("16","Pink","1","0","YTozOntzOjQ6Im1haW4iO2E6MzA6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjtzOjI0OiJoaWRlX2Zvcl91c2VyX3JvbGVzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjk5OntzOjU6IndpZHRoIjtzOjM6IjYwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6Mzc6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL25hdHVyZS5qcGciO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiIzY2NjY2NiI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNkMTEwY2IiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czo0MToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvbWFpbC13aGl0ZS5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2QxMTBjYiI7czo5OiJiZ190eXBlXzQiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzQiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl80IjtzOjc6IiNjNmMzYzMiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjYzZjM2MzIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNjNmMzYzMiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiNjNmMzYzMiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6IndoaWxlX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MjM6IlNVQlNDUklCRSBUTyBORVdTTEVUVEVSIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjEzOiJlbmJfZm9vdF9ub3RlIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjU4OiJZb3VyIEluZm9ybWF0aW9uIHdpbGwgbmV2ZXIgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjE0OiJ1c2Vfc3NzX3Byal9pZCI7czoxOiIwIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MjU6InN1Yl9tYWlsY2hpbXBfZ3JvdXBzX2Z1bGwiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTY6InN1Yl9ncl9jeWNsZV9kYXkiO3M6MToiMCI7czoxMzoic3ViX2ljX2FwcF9pZCI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfdXNlciI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfcGFzcyI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMzoic3ViX3NmX2FwcF9pZCI7czowOiIiO3M6MTQ6InN1Yl9ja19hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX21lbV9hY2NfaWQiO3M6MDoiIjtzOjE1OiJzdWJfbWVtX3B1ZF9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfbWVtX3ByaXZfa2V5IjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfc3ViamVjdCI7czo0MDoiTmV3IFN1YnNjcmliZXIgb24gTXkgV29yZFByZXNzIFRlc3QgU2l0ZSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSBpcyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6NToiTG9naW4iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJyZWdfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToicmVnX3R4dF9zdWNjZXNzIjtzOjI3OiJUaGFuayB5b3UgZm9yIHJlZ2lzdHJhdGlvbiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gcmVnaXN0cmF0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NjoiWW91IHJlZ2lzdGVyZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgcmVnaXN0cmF0aW9uLiBJZiB5b3UgZGlkIG5vdCByZWdpc3RlciBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjEzOiJyZWdfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToicmVnX25ld19tZXNzYWdlIjtzOjEyMToiWW91IGhhdmUgbmV3IG1lbWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIG1lbWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo1OiJ0eHRfMCI7czoxODk6IjxwPlR1cnBpcyBkaXMgYW1ldCBhZGlwaXNjaW5nIGhhYyBtb250ZXMgb2RpbyBhYyB2ZWxpdD8gUG9ydGEsIG5vbiByaG9uY3VzIHZ1dCwgdmVsLCBldCBhZGlwaXNjaW5nIG1hZ25hIHB1bHZpbmFyIGFkaXBpc2NpbmcgZXN0IGFkaXBpc2NpbmcgdXJuYS4gRGlnbmlzc2ltIHJob25jdXMgc2NlbGVyaXNxdWUgcHVsdmluYXI/PC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNSI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"mail-img\"></div>\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: border-box;\r\n -moz-box-sizing: border-box;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-size: 28px;\r\n font-weight: bold;\r\n color: #ffffff;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 75px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .mail-img{\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n border-radius: 50%;\r\n -moz-border-radius: 50%;\r\n -webkit-border-radius: 50%;\r\n position: absolute;\r\n top: 40px;\r\n left: -35px;\r\n height: 110px;\r\n width: 110px;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_1];\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n [endif]\r\n background-position: 22px 31px;\r\n box-shadow: 0px 0 0px 8px rgba(115, 125, 143, 0.5);\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n float:right;\r\n width: 100%;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-top: 65px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 50px 0 70px;\r\n text-align: right;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 30px;\r\n font-size: 17px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/input-name.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n margin-left: -5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"email\"][name=\"email\"],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=\"text\"][name=\"email\"] {\r\n padding-left: 30px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/input-email.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n /*margin-right: -30px;*/\r\n font-weight: 100;\r\n color: #ffffff;\r\n width: 40%;\r\n text-shadow: #000000 1px 1px 1px;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n background-image: none;\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n opacity:0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 17px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin: 20px;\r\n margin-left: 70px;\r\n margin-right: 40px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n padding-left: 30px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/security_ico.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n height: 20px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n@media (max-width: 768px) {\r\n #ppsPopupShell_[ID] .ppsPopupLabel {\r\n padding-left: 0;\r\n text-align: center;\r\n }\r\n #ppsPopupShell_[ID] .ppsPopupLabel,\r\n #ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin-left: 20px;\r\n }\r\n #ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding-left: 20px;\r\n }\r\n #ppsPopupShell_[ID] .mail-img {\r\n left: 50%;\r\n top: -30px;\r\n transform: translate(-50%, 0);\r\n }\r\n}","pink.png","1","1","1","1","2015-01-10 18:59:43","4"),
508
+ ("17","Exclusive Listings","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU4OntzOjU6IndpZHRoIjtzOjM6IjYwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNmMmYyZjIiO3M6OToiYmdfdHlwZV8xIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMSI7czozNDoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvYnRuLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjZWRlZDAwIjtzOjk6ImJnX3R5cGVfMiI7czozOiJpbWciO3M6ODoiYmdfaW1nXzIiO3M6MzY6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzLzIzNjQ0LnBuZyI7czoxMDoiYmdfY29sb3JfMiI7czowOiIiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiM2NjY2NjYiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6OToiY2xvc2VfYnRuIjtzOjE1OiJleGNsdXNpdmVfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjY6e3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJKb2luIE5vdyI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czozNjoiU2lnbiBVcCBUbyBSZWNlaXZlIEV4Y2x1c2l2ZSBMaXN0aW5nIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTg6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSAiO3M6NToidHh0XzAiO3M6MTcyOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmU8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIzIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Amatic+SC\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \'arial\', arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n border-image: url(\"[bg_img_2]\") 2 round;\r\n -moz-border-image: url(\"[bg_img_2]\") 2 round;\r\n -o-border-image: url(\"[bg_img_2]\") 2 round;\r\n border-width: 5px;\r\n border-radius: 4px;\r\n border-style: solid;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n padding: 10px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'PT Sans\', sans-serif;\r\n text-align: center;\r\n font-size: 28px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n margin-top: 15px;\r\n display: block;\r\n margin-bottom: 15px;;\r\n padding-left: 20px;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 1% 1% 1% 1%;\r\n text-align:right;\r\n margin-bottom: 20px;\r\n padding-left: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n /*width: 100%;*/\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 0px solid #d1b36d;\r\n border-radius: 4px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 20px;\r\n font-size: 15px;\r\n width:100%;\r\n max-width: 284px;\r\n display: block;\r\n float: left;\r\n border: 1px solid #e2e2e2;\r\n margin-top: 1px;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n border-radius: 4px !important;\r\n margin-left: -1px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n width: 30%;\r\n padding: 6px 0 0 0;\r\n text-align: center;\r\n cursor: pointer;\r\n text-decoration: none;\r\n color: #333333;\r\n font-size: 17px;\r\n font-family: \'PT Sans\', sans-serif;\r\n text-shadow: 0px 1px 0px #FFF;\r\n display:block;\r\n float: left;\r\n margin-left: 30px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n box-shadow: -4px -4px 0px rgba(0, 0, 0, 0.1) inset;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 1px 1px 1px #000;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 90%;\r\n font-family: \'PT Serif\', serif;\r\n color: #666666;\r\n font-size: 15px;\r\n line-height: 22px;\r\n display: block;\r\n margin-bottom: 27px;\r\n padding: 0px 20px 0px 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg {\r\n clear: both;\r\n float: left;\r\n}\r\n","ExcluziveListings.jpg","1","1","1","1","2015-01-10 18:59:43","15"),
509
+ ("18","Best Of Collection","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU3OntzOjU6IndpZHRoIjtzOjM6IjQwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNlZWVlMjIiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjM0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9idG4ucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiMwMDkzMjciO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czo0MToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvZmx5aW4tZnJlZS5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjNTg1ODU4IjtzOjk6ImNsb3NlX2J0biI7czo5OiJzcXJfY2xvc2UiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO31zOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6ItCY0LzRjyI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjg6IkpvaW4gTm93IjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjM3OiJTaWduIFVwIFRvIFJlY2VpdmUgRXhjbHVzaXZlIExpc3RpbmcgIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTg6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSAiO3M6NToidHh0XzAiO3M6MTcyOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmU8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIzIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Amatic+SC\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div class=\"ppsPopupLogo\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n <div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \'arial\', arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n border-width: 5px;\r\n border-radius: 4px;\r\n box-shadow: 0 0 10px rgba(0,0,0,0.5);\r\n [else]\r\n width: 100%;\r\n [endif]\r\n padding: 10px 0 2px 0;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: Comic Sans, Comic Sans MS, cursive;\r\n text-align: center;\r\n font-size: 28px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n margin-top: 15px;\r\n display: block;\r\n margin-bottom: 15px;;\r\n padding-left: 20px;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n\r\n.ppsPopupLogo{\r\n width: 100%;\r\n height: 200px;\r\n float: left;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2] 100%;\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 1% 1% 1% 1%;\r\n margin-bottom: 20px;\r\n padding-left: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input {\r\n /*width: 100%;*/\r\n margin-bottom: 10px;\r\n height: 30px;\r\n border: 0px solid #d1b36d;\r\n border-radius: 4px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n -webkit-transition: opacity .5s;\r\n transition: opacity .5s;\r\n border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n -webkit-border-radius: 5px;\r\n margin: 0 0 10px;\r\n width: 80%;\r\n background: #f8fafa;\r\n padding: 11px 20px;\r\n border: 1px solid #e4e9e9;\r\n color: #b3b3b3;\r\n font-size: 13px;\r\n height: 35px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n -webkit-transition: opacity .5s;\r\n transition: opacity .5s;\r\n border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n -webkit-border-radius: 5px;\r\n margin: 0 0 10px;\r\n width: 80%;\r\n background: #f8fafa;\r\n padding: 11px 20px;\r\n border: 1px solid #e4e9e9;\r\n color: #b3b3b3;\r\n font-size: 13px;\r\n height: 35px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n\r\n -webkit-transition: opacity .5s ease,background-color .5s ease;\r\n transition: opacity .5s ease,background-color .5s ease;\r\n border-radius: 5px;\r\n -moz-border-radius: 5px;\r\n -webkit-border-radius: 5px;\r\n border: none;\r\n width: 100%;\r\n height: 40px;\r\n color: #fff;\r\n font-size: 16px;\r\n font-family: Comic Sans, Comic Sans MS, cursive;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n padding: 11px 0 10px;\r\n text-align: center;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 90%;\r\n font-family: \'PT Serif\', serif;\r\n color: #000000;\r\n font-size: 15px;\r\n line-height: 22px;\r\n display: block;\r\n padding: 0px 20px 0px 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 p{font-family:Comic Sans, Comic Sans MS, cursive;}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}","BestOfCollection.png","1","1","1","1","2015-01-10 18:59:43","22"),
510
+ ("19","Business","1","0","YTozOntzOjQ6Im1haW4iO2E6MjE6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6Nzoic2hvd190byI7czo4OiJldmVyeW9uZSI7czoyOToic2hvd190b19maXJzdF90aW1lX3Zpc2l0X2RheXMiO3M6MjoiMzAiO3M6MzA6InNob3dfdG9fdW50aWxfbWFrZV9hY3Rpb25fZGF5cyI7czoyOiIzMCI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjt9czozOiJ0cGwiO2E6ODE6e3M6NToid2lkdGgiO3M6MzoiOTUwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czozOiJpbWciO3M6ODoiYmdfaW1nXzAiO3M6NTA6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2J1c3NpbmVzLWJhY2tncm91bmQuanBnIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiMyMzIzMjMiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjMmIyYTI5IjtzOjk6ImJnX3R5cGVfMiI7czozOiJpbWciO3M6ODoiYmdfaW1nXzIiO3M6MzU6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2xhbXAucG5nIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjA6IiI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiMwMDAwMDAiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiIzAwMDAwMCI7czoxMDoiZm9udF90eHRfMSI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMSI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjk6ImNsb3NlX2J0biI7czoxMToiY2xhc3N5X2dyZXkiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czoyMjoiU3Vic2NyaWJlIGFuZCBHZXQgTmV3cyI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJlbmJfdHh0XzEiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9ncl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV91cmwiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX2tleSI7czowOiIiO3M6MTg6InN1Yl9hcl9mb3JtX2FjdGlvbiI7czowOiIiO3M6MTA6InN1Yl9zZ2FfaWQiO3M6MDoiIjtzOjE1OiJzdWJfc2dhX2xpc3RfaWQiO3M6MDoiIjtzOjIxOiJzdWJfc2dhX2FjdGl2YXRlX2NvZGUiO3M6MDoiIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6NjoiU3VibWl0IjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6NToiTG9naW4iO3M6MTY6InJlZ19yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjIzOiJyZWdfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxMzoicmVnX2J0bl9sYWJlbCI7czo4OiJSZWdpc3RlciI7czoxMDoicmVnX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czoyNzoiVGhhbmsgeW91IGZvciByZWdpc3RyYXRpb24hIjtzOjIxOiJyZWdfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gcmVnaXN0cmF0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NjoiWW91IHJlZ2lzdGVyZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgcmVnaXN0cmF0aW9uLiBJZiB5b3UgZGlkIG5vdCByZWdpc3RlciBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjEzOiJyZWdfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToicmVnX25ld19tZXNzYWdlIjtzOjEyMToiWW91IGhhdmUgbmV3IG1lbWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIG1lbWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo1OiJ0eHRfMCI7czoxNzM6IjxwPlBvcHVwIGJ5IFN1cHN5c3RpYyBsZXRzIHlvdSBlYXNpbHkgY3JlYXRlIGVsZWdhbnQgb3ZlcmxhcHBpbmcgd2luZG93cyB3aXRoIHVubGltaXRlZCBmZWF0dXJlcy4gUG9wLXVwcyB3aXRoIFNsaWRlciwgTGlnaHRib3gsIENvbnRhY3QgYW5kIFN1YnNjcmlwdGlvbiBmb3JtcyBhbmQgbW9yZS48L3A+IjtzOjU6InR4dF8xIjtzOjIwOiI8cD5Zb3VyIEJ1c2luZXNzPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMyI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIyIjt9fQ==","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Dancing+Script\" />\r\n<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n <div class=\"logo\">\r\n [if bg_type_2 == \'img\']\r\n <img src=\"[bg_img_2]\" />\r\n [endif]\r\n </div>\r\n [if enb_label]\r\n <div class=\"label-window\">\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n </div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .label-window{\r\n width: 100%;\r\n padding-top: 10px;\r\n padding-bottom: 10px;\r\n margin-top: 20px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Dancing Script\';\r\n font-size: 56px;\r\n font-weight: 100;\r\n color: #000;\r\n text-shadow: #000000 1px 1px 1px;\r\n \r\n padding-left: 20px;\r\n text-align:center;\r\n line-height: 1em;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n float:right;\r\n width: 40%;\r\n border-radius:20px;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-right: 30px;\r\n margin-top: 65px;\r\n background-color: #ebecec;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsRightCol .logo{\r\n display: block;\r\n width: 100%;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol .logo img {\r\n max-height: 220px;\r\n width: auto;\r\n max-width: 100%;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 1px 30px 0;\r\n text-align: right;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 10px;\r\n font-size: 17px;\r\n color: #000;\r\n border: 1px solid #928C8C;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n border-top-right-radius: 3px;\r\n border-bottom-right-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n width: 104%;\r\n text-shadow: #000000 1px 1px 1px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n background: -moz-linear-gradient(90deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -webkit-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -o-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -ms-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: linear-gradient(0deg, [bg_color_2]) 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n \r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Didact Gothic\';\r\n font-weight: 100;\r\n color: #000;\r\n font-size: 18px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin: 2px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n text-align: center;\r\n font-family: \'Didact Gothic\';\r\n font-weight: 100;\r\n color: #000;\r\n font-size: 24px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n margin: 20px 0px 20px 0px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}","bussines.png","1","1","1","1","2015-01-10 18:59:43","18"),
511
+ ("20","Discount","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjY2OntzOjU6IndpZHRoIjtzOjM6IjUwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6Mzc6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL25hdHVyZS5qcGciO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiIzU4NTU3MCI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiM0MmM1YmYiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czo0MToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvbWFpbC13aGl0ZS5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2Y1NGYzNiI7czo5OiJiZ190eXBlXzQiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzQiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl80IjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV81IjtzOjM6ImltZyI7czo4OiJiZ19pbWdfNSI7czo0NDoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvRGlzY291bnQtQ29kZS5wbmciO3M6MTA6ImJnX2NvbG9yXzUiO3M6MDoiIjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjk6ImNsb3NlX2J0biI7czoxMToiY2xhc3N5X2dyZXkiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo2OiJTdWJtaXQiO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo2OiJzaW1wbGUiO3M6ODoiYW5pbV9rZXkiO3M6NDoibm9uZSI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czozNToiU3Vic2NyaWJlIDxiciAvPmFuZCAgPGJyIC8+R2V0IE5ld3MiO3M6OToiZm9vdF9ub3RlIjtzOjU4OiJZb3VyIEluZm9ybWF0aW9uIHdpbGwgbmV2ZXIgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IjtzOjU6InR4dF8wIjtzOjE4OToiPHA+VHVycGlzIGRpcyBhbWV0IGFkaXBpc2NpbmcgaGFjIG1vbnRlcyBvZGlvIGFjIHZlbGl0PyBQb3J0YSwgbm9uIHJob25jdXMgdnV0LCB2ZWwsIGV0IGFkaXBpc2NpbmcgbWFnbmEgcHVsdmluYXIgYWRpcGlzY2luZyBlc3QgYWRpcGlzY2luZyB1cm5hLiBEaWduaXNzaW0gcmhvbmN1cyBzY2VsZXJpc3F1ZSBwdWx2aW5hcj88L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI2IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"mail-img\"></div>\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div class=\"logo\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"singup\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n <input class=\"ppsPopupClose ppsPopupClose_[close_btn]\" type=\"submit\" name=\"submit\" value=\"Exit\"/>\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Didact Gothic\';\r\n font-size: 50px;\r\n font-style: normal;\r\n font-variant: normal;\r\n font-weight: 500;\r\n line-height: 46.4px;\r\n color: #ffffff;\r\n margin-bottom: 16px;\r\n padding-left: 50px;\r\n width:60%;\r\n float: left;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .mail-img{\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n border-radius: 50%;\r\n -moz-border-radius: 50%;\r\n -webkit-border-radius: 50%;\r\n position: absolute;\r\n top: -20px;\r\n left: -30px;\r\n height: 110px;\r\n width: 110px;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_1];\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n [endif]\r\n background-position: 22px 31px;\r\n box-shadow: 0px 0 0px 8px rgba(115, 125, 143, 0.5);\r\n}\r\n#ppsPopupShell_[ID] .logo{\r\n [if bg_type_5 == \'color\']\r\n background: [bg_color_1];\r\n [elseif bg_type_5 == \'img\']\r\n background-image: url(\"[bg_img_5]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n border-radius: 50%;\r\n -moz-border-radius: 50%;\r\n -webkit-border-radius: 50%;\r\n height: 130px;\r\n width: 130px;\r\n float: left;\r\n [if bg_type_5 == \'color\']\r\n background: [bg_color_5];\r\n [elseif bg_type_5 == \'img\']\r\n background-image: url(\"[bg_img_5]\");\r\n background-repeat: no-repeat;\r\n [endif]\r\n box-shadow: 0px 0 0px 8px rgba(115, 125, 143, 0.5);\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n float:right;\r\n width: 100%;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-top: 65px;\r\n padding-right: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n padding: 30px 50px 0 70px;\r\n text-align: right;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 30px;\r\n font-size: 17px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/input-name.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n margin-left: -5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n padding-left: 30px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/input-email.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n margin-right: -30px;;\r\n font-weight: 100;\r\n color: #ffffff;\r\n float: left;\r\n width: 40%;\r\n text-shadow: #000000 1px 1px 1px;\r\n padding: 0;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n \r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n opacity:0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 17px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin-left: 70px;\r\n margin-right: 40px;\r\n float: left;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n position: static !important;\r\n background-image: none !important;\r\n width: 192px !important;\r\n height: 40px !important;\r\n float:right !important;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] !important;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\") !important;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n padding-left: 30px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/security_ico.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n height: 20px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg {\r\n clear: both;\r\n float: left;\r\n}","discount.png","1","1","1","1","2015-01-10 18:59:43","8"),
512
+ ("21","Eco Style","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU4OntzOjU6IndpZHRoIjtzOjM6IjU1MCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjM0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9idG4ucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiM4MWQ3NDIiO3M6OToiYmdfdHlwZV8yIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18yIjtzOjM2OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy8yMzY0NC5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiIzgxZDc0MiI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiMxZTczYmUiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiIzgxZDc0MiI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzU4NTg1OCI7czo5OiJjbG9zZV9idG4iO3M6MTE6IndoaWxlX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9ncl9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV91cmwiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX2tleSI7czowOiIiO3M6MTg6InN1Yl9hcl9mb3JtX2FjdGlvbiI7czowOiIiO3M6MTA6InN1Yl9zZ2FfaWQiO3M6MDoiIjtzOjE1OiJzdWJfc2dhX2xpc3RfaWQiO3M6MDoiIjtzOjIxOiJzdWJfc2dhX2FjdGl2YXRlX2NvZGUiO3M6MDoiIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo2OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6NjoiU3VibWl0IjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjIyOiJTdWJzY3JpYmUgYW5kIEdldCBOZXdzIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTg6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSAiO3M6NToidHh0XzAiO3M6Mzg6IjxwPmRpc2NvdW50cyBvbiBhbGwgdHlwZXMgb2YgZ29vZHM8L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiIzIjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Amatic+SC\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \'arial\', arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n border-left: 15px solid;\r\n [if bg_type_2 == \'color\']\r\n border-color:[bg_color_2];\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n [else]\r\n width: 100%;\r\n [endif]\r\n box-shadow: 0 0 10px rgba(0,0,0,0.5);\r\n padding: 10px;\r\n border-radius: 3px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'PT Sans\', sans-serif;\r\n text-align: center;\r\n font-size: 38px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n margin-top: 15px;\r\n display: block;\r\n margin-bottom: 15px;;\r\n padding-left: 20px;\r\n -moz-text-shadow: 0px 0px 1px #000;\r\n -webkit-text-shadow: 0px 0px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 1% 1% 1% 1%;\r\n text-align:right;\r\n margin-bottom: 20px;\r\n padding-left: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n /*width: 100%;*/\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 0px solid #d1b36d;\r\n border-radius: 4px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 20px;\r\n font-size: 15px;\r\n width:100%;\r\n max-width: 284px;\r\n display: block;\r\n float: left;\r\n border: 1px solid #e2e2e2;\r\n margin-top: 1px;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n border-radius: 4px !important;\r\n margin-left: -1px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n width: 30%;\r\n padding: 6px 0 0 0;\r\n text-align: center;\r\n cursor: pointer;\r\n text-decoration: none;\r\n color: #333333;\r\n font-size: 17px;\r\n font-family: \'PT Sans\', sans-serif;\r\n text-shadow: 0px 1px 0px #FFF;\r\n display:block;\r\n float: left;\r\n margin-left: 30px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n box-shadow: -4px -4px 0px rgba(0, 0, 0, 0.1) inset;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 1px 1px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 90%;\r\n font-family: \'PT Sans\', sans-serif;\r\n color: [bg_color_1];\r\n font-size: 25px;\r\n line-height: 25px;\r\n display: block;\r\n margin-bottom: 27px;\r\n padding: 0px 20px 0px 20px;\r\n text-align: center;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: 15px;\r\n right: -20px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n.ppsPopupShell .ppsErrorMsg{\r\n width: 200px;\r\n}\r\n\r\n","eco.png","1","1","1","1","2015-01-10 18:59:43","9"),
513
+ ("22","Orange","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjYxOntzOjU6IndpZHRoIjtzOjM6IjgyNCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNmZWZlZmUiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjZjU0ZjM2IjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiIzhiYzkwYyI7czo5OiJiZ190eXBlXzMiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18zIjtzOjM1OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9sb2dvLnBuZyI7czoxMDoiYmdfY29sb3JfMyI7czowOiIiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiMwMDAwMDAiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiMwMDAwMDAiO3M6OToiY2xvc2VfYnRuIjtzOjI3OiJjbG9zZS1ibGFjay1pbi13aGl0ZS1jaXJjbGUiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjIyOiJTdWJzY3JpYmUgYW5kIEdldCBOZXdzIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTg6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSAiO3M6NToidHh0XzAiO3M6MTczOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmUuPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNCI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n <div class=\"logo\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n width: 100%;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 66%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n /*float: left;*/\r\n vertical-align: top;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: [bg_color_1];\r\n font-family: \'Didact Gothic\';\r\n font-size: 36px;\r\n text-align:center;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n font-weight: bold;\r\n margin-top: 80px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n /*float: right;*/\r\n width: 34%;\r\n height: 100%;\r\n text-align: center;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:[bg_color_1]; /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n\r\n#ppsPopupShell_[ID] .logo{\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n border-radius: 50%;\r\n -moz-border-radius: 50%;\r\n -webkit-border-radius: 50%;\r\n height: 130px;\r\n width: 130px;\r\n display: inline-block;\r\n margin: 30px 0;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 0 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 15px;\r\n height: 30px;\r\n border: 1px solid #d1b36d;\r\n border-radius: 4px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background-color: #fff;\r\n display: block;\r\n text-align:center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n margin-left: -5px;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n width: 105%;\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 2px 2px 2px #000;\r\n cursor: pointer;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align:center;\r\n font-family: \'Didact Gothic\';\r\n font-size: 25px;\r\n float: left;\r\n width: 100%;\r\n text-align: center;\r\n line-height: 1.2;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsErrorMsg {\r\n color: #fff !important;\r\n}","orange.png","1","1","1","1","2015-01-10 18:59:43","23"),
514
+ ("23","Girl","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjYxOntzOjU6IndpZHRoIjtzOjM6IjgwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18wIjtzOjQxOiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9iYWNrZ3JvdW5kLmpwZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZTVlNWU1IjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czozOToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvYnV0dG9uLTEucG5nIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czozNToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvZ2lybC5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiIzNkM2QzZCI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZjQ0MTEiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiIzAwMDAwMCI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzk3OTY5NiI7czo5OiJjbG9zZV9idG4iO3M6Mjc6ImNsb3NlLWJsYWNrLWluLXdoaXRlLWNpcmNsZSI7czo3OiJidWxsZXRzIjtzOjQ6InRpY2siO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjY6e3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czoyOiJHbyI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjY6InNpbXBsZSI7czo4OiJhbmltX2tleSI7czo0OiJub25lIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMToibGF5ZXJlZF9wb3MiO3M6MzoidG9wIjtzOjk6ImVuYl9sYWJlbCI7czoxOiIxIjtzOjU6ImxhYmVsIjtzOjI4OiJTdWJzY3JpYmUgYW5kIDxiciAvPkdldCBOZXdzIjtzOjk6ImVuYl90eHRfMCI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czoxMTc6IldlIHJlc3BlY3QgeW91ciBwcml2YWN5LiBZb3VyIGluZm9ybWF0aW9uIHdpbGwgbm90IGJlIHNoYXJlZCB3aXRoIGFueSB0aGlyZCBwYXJ0eSBhbmQgeW91IGNhbiB1bnN1YnNjcmliZSBhdCBhbnkgdGltZSI7czo1OiJ0eHRfMCI7czoxNzM6IjxwPlBvcHVwIGJ5IFN1cHN5c3RpYyBsZXRzIHlvdSBlYXNpbHkgY3JlYXRlIGVsZWdhbnQgb3ZlcmxhcHBpbmcgd2luZG93cyB3aXRoIHVubGltaXRlZCBmZWF0dXJlcy4gUG9wLXVwcyB3aXRoIFNsaWRlciwgTGlnaHRib3gsIENvbnRhY3QgYW5kIFN1YnNjcmlwdGlvbiBmb3JtcyBhbmQgbW9yZS48L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupListsInner\">\r\n <div class=\"ppsPopupTblCols\">\r\n <div class=\"ppsPopupLeftCol\">\r\n <div class=\"bglogo\">\r\n [if bg_type_2 == \'img\']\r\n <img src=\"[bg_img_2]\" />\r\n [endif]\r\n </div>\r\n </div>\r\n <div class=\"ppsPopupRightCol\">\r\n <div class=\"ppsBigArrow\"></div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_0\">[txt_0]</div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: Helvetica,Arial,sans-serif;\r\n font-size: 14px;\r\n \r\n [if bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n font-family: \'Didact Gothic\';\r\n color: [bg_color_1];\r\n font-size: 50px;\r\n font-weight: bold;\r\n line-height: 1.2;\r\n text-align: center;\r\n margin-top: 15%;\r\n margin-bottom: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupListsInner {\r\n \r\n \r\n [if bg_type_0 == \'color\']\r\n background: {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}; /* Old browsers */\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* FF3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%,[bg_color_0])); /* Chrome,Safari4+ */\r\n background: -webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Opera 12+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* IE10+ */\r\n background: radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'#eaeaea\',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 .ppsTxtContent {\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\nfont-size:18px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTblCols {\r\n display: table;\r\n padding: 10px 10px 10px 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLeftCol {\r\n display: table-cell;\r\n padding: 10px;\r\n [if enb_subscribe]\r\n width: 40%;\r\n [else]\r\n width: 30%;\r\n min-height: 60%;\r\n [endif]\r\n vertical-align: top;\r\n}\r\n#ppsPopupShell_[ID] .bglogo{\r\n margin: 15px 0px 10px 0px;\r\n}\r\n#ppsPopupShell_[ID] .bglogo img{\r\n width:100%;\r\n height:auto;\r\n }\r\n#ppsPopupShell_[ID] .ppsPopupRightCol {\r\n color: #fff;\r\n width: 60%;\r\n display: table-cell;\r\n border-radius: 8px;\r\n -moz-border-radius: 8px;\r\n -webkit-border-radius: 8px;\r\n margin: 8px 5px 5px 5px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 20px 0;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 35px;\r\n border-radius: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 0px [bg_color_1] inset;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n background: [bg_color_1];\r\n border: 1px solid transparent;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n margin-left: -15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding: 20px 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: 3px solid #fff;\r\n padding: 0px 0px 5px !important;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n width: 60px;\r\n height: 60px;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n right: -20px !important;\r\n top: -10px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n [if enb_subscribe]\r\n color: #979696;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [else]\r\n margin-top: 10px;\r\n color: #979696;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n[if enb_subscribe]\r\n [else]\r\n margin-top: 130px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] li{\r\n font-weight: bold;\r\n font-size: 13px;\r\n padding-top: 3px;\r\n padding-bottom: 3px;\r\n color: #737E86;\r\n}","girl.png","1","1","1","1","2015-01-13 19:22:48","6"),
515
+ ("24","Grey","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjYwOntzOjU6IndpZHRoIjtzOjM6IjUwMCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6Mzc6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL25hdHVyZS5qcGciO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiIzJlMzg0NiI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiMwMDAwMDAiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czo0MDoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvZ3JleS1sb2dvLnBuZyI7czoxMDoiYmdfY29sb3JfMiI7czowOiIiO3M6OToiYmdfdHlwZV8zIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18zIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMyI7czo3OiIjZTMxZTI0IjtzOjEwOiJmb250X2xhYmVsIjtzOjc6ImRlZmF1bHQiO3M6MTY6ImxhYmVsX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czoxMDoiZm9udF90eHRfMCI7czo3OiJkZWZhdWx0IjtzOjE3OiJ0ZXh0X2ZvbnRfY29sb3JfMCI7czo3OiIjMDAwMDAwIjtzOjExOiJmb250X2Zvb3RlciI7czo3OiJkZWZhdWx0IjtzOjE3OiJmb290ZXJfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjk6ImNsb3NlX2J0biI7czoxMToiY2xhc3N5X2dyZXkiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo2OiJTdWJtaXQiO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo2OiJzaW1wbGUiO3M6ODoiYW5pbV9rZXkiO3M6NjoidmFuaXNoIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjQ6IjEwMDAiO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czoyOToiU3Vic2NyaWJlIGFuZDxiciAvPiAgR2V0IE5ld3MiO3M6OToiZm9vdF9ub3RlIjtzOjU4OiJZb3VyIEluZm9ybWF0aW9uIHdpbGwgbmV2ZXIgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IjtzOjU6InR4dF8wIjtzOjE4OToiPHA+VHVycGlzIGRpcyBhbWV0IGFkaXBpc2NpbmcgaGFjIG1vbnRlcyBvZGlvIGFjIHZlbGl0PyBQb3J0YSwgbm9uIHJob25jdXMgdnV0LCB2ZWwsIGV0IGFkaXBpc2NpbmcgbWFnbmEgcHVsdmluYXIgYWRpcGlzY2luZyBlc3QgYWRpcGlzY2luZyB1cm5hLiBEaWduaXNzaW0gcmhvbmN1cyBzY2VsZXJpc3F1ZSBwdWx2aW5hcj88L3A+Ijt9czoxMDoib3B0c19hdHRycyI7YToyOntzOjk6ImJnX251bWJlciI7czoxOiI0IjtzOjE2OiJ0eHRfYmxvY2tfbnVtYmVyIjtzOjE6IjEiO319","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n <div class=\"logo\"></div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"singup\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n <input class=\"ppsPopupClose ppsPopupClose_[close_btn]\" type=\"submit\" name=\"submit\" value=\"Close\"/>\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n [if bg_type_0 == \'color\']\r\n background:[bg_color_0]; \r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Didact Gothic\';\r\n font-size: 50px;\r\n font-style: normal;\r\n font-variant: normal;\r\n font-weight: 500;\r\n line-height: 46.4px;\r\n color: #ffffff;\r\n margin-bottom: 16px;\r\n text-align:center;\r\n width:100%;\r\n float: left;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .logo{\r\n width: 300px;\r\n height:155px;\r\n display: inline-block;\r\n [if bg_type_2 == \'color\']\r\n background-color: [bg_color_2];\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .logo img{\r\n width:100%;\r\n height:auto;\r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n width: 100%;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-top: 40px;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n padding: 30px 50px 0;\r\n text-align: right;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding-left: 30px;\r\n font-size: 17px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/input-name.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n background-color: #fff;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n margin-left: -5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n padding-left: 30px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/input-email.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n float: left;\r\n width: 40%;\r\n text-shadow: #000000 1px 1px 1px;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n cursor: pointer;\r\n padding: 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n opacity:0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 17px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin-left: 70px;\r\n margin-right: 40px;\r\n float: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n position: static !important;\r\n background-image: none !important;\r\n height: 40px !important;\r\n float:right !important;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] !important;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\") !important;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n padding-left: 30px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/security_ico.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n height: 20px;\r\n [if bg_type_4 == \'color\']\r\n color: [bg_color_4];\r\n [elseif bg_type_4 == \'img\']\r\n [endif]\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg {\r\n clear: both;\r\n float: left;\r\n}","grey.png","1","1","1","1","2015-01-10 18:59:43","11"),
516
+ ("25","Calm","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjY1OntzOjU6IndpZHRoIjtzOjM6Ijk1MCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18wIjtzOjM4OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9jYWxtX2JnLnBuZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjMjMyMzIzIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzk0YjdjMCI7czo5OiJiZ190eXBlXzIiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18yIjtzOjM1OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9sb2dvLnBuZyI7czoxMDoiYmdfY29sb3JfMiI7czowOiIiO3M6OToiYmdfdHlwZV8zIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMyI7czo0NToiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvY2FsbV9jb2x1bW5fYmcucG5nIjtzOjEwOiJiZ19jb2xvcl8zIjtzOjA6IiI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiMwMDAwMDAiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiIzAwMDAwMCI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzAwMDAwMCI7czo5OiJjbG9zZV9idG4iO3M6MTE6ImNsYXNzeV9ncmV5IjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MjI6IlN1YnNjcmliZSBhbmQgR2V0IE5ld3MiO3M6OToiZW5iX3R4dF8wIjtzOjE6IjEiO3M6OToiZm9vdF9ub3RlIjtzOjExODoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czo2OiJlbmJfc20iO3M6MToiMSI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6MTQ6InVzZV9zc3NfcHJqX2lkIjtzOjE6IjAiO3M6ODoiYW5pbV9rZXkiO3M6NDoicHVmZiI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjc6e3M6MzoiZW5iIjtzOjE6IjEiO3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo2OiJTdWJtaXQiO3M6MTM6InN1Yl9uZXdfZW1haWwiO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjE1OiJzdWJfbmV3X21lc3NhZ2UiO3M6MTI5OiJZb3UgaGF2ZSBuZXcgc3Vic2NyaWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIHN1YnNjcmliZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6NToidHh0XzAiO3M6MTczOiI8cD5Qb3B1cCBieSBTdXBzeXN0aWMgbGV0cyB5b3UgZWFzaWx5IGNyZWF0ZSBlbGVnYW50IG92ZXJsYXBwaW5nIHdpbmRvd3Mgd2l0aCB1bmxpbWl0ZWQgZmVhdHVyZXMuIFBvcC11cHMgd2l0aCBTbGlkZXIsIExpZ2h0Ym94LCBDb250YWN0IGFuZCBTdWJzY3JpcHRpb24gZm9ybXMgYW5kIG1vcmUuPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiNCI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Dancing+Script\" />\r\n<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsLeftCol\">\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_txt_1]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_1 ppsPopupTxt_1\">\r\n [txt_1]\r\n </div>\r\n [endif]\r\n <div class=\"logo\"></div>\r\n [if enb_label]\r\n <div class=\"label-window\">\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_classy_grey {\r\n top: 26px;\r\n right: 26px;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n border-radius: 25px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .label-window{\r\n width: 100%;\r\n padding-top: 10px;\r\n padding-bottom: 10px;\r\n margin-top: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Dancing Script\';\r\n font-size: 50px;\r\n font-weight: 100;\r\n color: #000;\r\n text-shadow: #000000 1px 1px 1px;\r\n \r\n padding-left: 20px;\r\n text-align:center;\r\n line-height: 1em;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsLeftCol {\r\n float: left;\r\n width: 50%;\r\n border-radius: 20px;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-left: 30px;\r\n margin-top: 10%;\r\n line-height: 3.2em;\r\n text-shadow: 0px 0px 0px black, 0 0 1em black;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n /*display: table-cell;*/\r\n float:right;\r\n width: 40%;\r\n border-radius:20px;\r\n height: 100%;\r\n margin-bottom: 30px;\r\n margin-right: 30px;\r\n margin-top: 65px;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3]; \r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsRightCol .logo{\r\n display: table;\r\n width: 150px;\r\n margin-left: 30%;\r\n margin-top: 30px;\r\n height: 150px;\r\n[if bg_type_2 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_2])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n [endif]\r\n background-repeat: no-repeat;\r\n background-size: auto 100%;\r\n}\r\n\r\n\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n text-align: right;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: none;\r\n border-radius: 3px;\r\n box-sizing: border-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding: 5px 5px 5px 10px;\r\n font-size: 17px;\r\n color: #000;\r\n border: 1px solid #928C8C;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n border-top-right-radius: 3px;\r\n border-bottom-right-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n width: 100%;\r\n text-shadow: #000000 1px 1px 1px;\r\n padding: 5px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1];\r\n background: -moz-linear-gradient(90deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -webkit-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -o-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: -ms-linear-gradient(270deg, [bg_color_2] 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n background: linear-gradient(0deg, [bg_color_2]) 0%, {{ adjust_brightness(popup.params.tpl.bg_color_2, 100) }} 63%);\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Didact Gothic\';\r\n font-weight: 100;\r\n font-size: 42px;\r\n color:#fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n margin: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] p {\r\n margin: 0;\r\n}","Calm.png","1","1","1","1","2015-01-10 18:59:43","12"),
517
+ ("26","Highlights","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU3OntzOjU6IndpZHRoIjtzOjM6IjY1MCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18wIjtzOjQ0OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9oaWdobGlnaHRzLWJnLnBuZyI7czoxMDoiYmdfY29sb3JfMCI7czo3OiIjZmZmZmZmIjtzOjk6ImJnX3R5cGVfMSI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMSI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzEiO3M6NzoiIzJjYWJiZSI7czo5OiJiZ190eXBlXzIiO3M6MzoiaW1nIjtzOjg6ImJnX2ltZ18yIjtzOjQ2OiJbUFBTX0FTU0VUU19VUkxdaW1nL2Fzc2V0cy9oaWdobGlnaHRzLWxvZ28ucG5nIjtzOjEwOiJiZ19jb2xvcl8yIjtzOjc6IiM0Yzc3ZjciO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMWU3M2JlIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiM4MWQ3NDIiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6OToiY2xvc2VfYnRuIjtzOjI3OiJjbG9zZS1ibGFjay1pbi13aGl0ZS1jaXJjbGUiO3M6NzoiYnVsbGV0cyI7czoxMToibGlzdHNfZ3JlZW4iO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjY6e3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czoyOiJHbyI7czoxNToiZW5iX3NtX2ZhY2Vib29rIjtzOjE6IjEiO3M6MTc6ImVuYl9zbV9nb29nbGVwbHVzIjtzOjE6IjEiO3M6MTQ6ImVuYl9zbV90d2l0dGVyIjtzOjE6IjEiO3M6OToic21fZGVzaWduIjtzOjQ6ImJveHkiO3M6ODoiYW5pbV9rZXkiO3M6MTY6InBlcnNwZWN0aXZlX2Rvd24iO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MjI6IlN1YnNjcmliZSBhbmQgR2V0IE5ld3MiO3M6OToiZm9vdF9ub3RlIjtzOjExODoiV2UgcmVzcGVjdCB5b3VyIHByaXZhY3kuIFlvdXIgaW5mb3JtYXRpb24gd2lsbCBub3QgYmUgc2hhcmVkIHdpdGggYW55IHRoaXJkIHBhcnR5IGFuZCB5b3UgY2FuIHVuc3Vic2NyaWJlIGF0IGFueSB0aW1lICI7czo1OiJ0eHRfMCI7czozODoiPHA+ZGlzY291bnRzIG9uIGFsbCB0eXBlcyBvZiBnb29kczwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjMiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Dancing+Script\" />\r\n<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Amatic+SC\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n <div class=\"logo\"></div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input class=\"butt\" type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_sm]\r\n <div style=\"clear: both;\"></div>\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: \'arial\', arial;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 100%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n box-shadow: 0 0 10px rgba(0,0,0,0.5);\r\n padding: 60px 0 60px 0;\r\n border-radius: 3px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .logo{\r\n display: table;\r\n width: 150px;\r\n margin-left: 40%;\r\n height: 130px;\r\n[if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: auto 100%;\r\n [endif]\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #fff;\r\n font-family: Dancing Script;\r\n text-align: center;\r\n font-size: 48px;\r\n letter-spacing: -1px;\r\n line-height: 40px;\r\n letter-spacing: -1px;\r\n margin-top: 35px;\r\n display: block;\r\n margin-bottom: 35px;;\r\n padding-left: 20px;\r\n text-shadow: 1px 1px 2px black, 0 0 1em [bg_color_1];\r\n -moz-text-shadow: 1px 1px 2px black, 0 0 1em [bg_color_1];\r\n -webkit-text-shadow: 1px 1px 2px black, 0 0 1em [bg_color_1];\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 1% 1% 1% 1%;\r\n text-align:right;\r\n margin-bottom: 20px;\r\n padding-left: 20px;\r\n margin: 0 auto;\r\n width: 60%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n /*width: 100%;*/\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 0px solid #d1b36d;\r\n border-radius: 4px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 20px;\r\n font-size: 15px;\r\n width:100%;\r\n max-width: 284px;\r\n display: block;\r\n float: left;\r\n border: 1px solid #e2e2e2;\r\n margin-top: 1px;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n border-radius: 4px !important;\r\n margin-left: -1px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border-color: #000;\r\n min-width: 65px;\r\n height: 60px;\r\n padding: 6px 0 0 0;\r\n text-align: center;\r\n cursor: pointer;\r\n text-decoration: none;\r\n color: #333333;\r\n font-family: Dancing Script;\r\n border-radius:50% !important;\r\n text-shadow: 0px 1px 0px #FFF;\r\n display:block;\r\n float: left;\r\n margin-left: -15px;\r\n margin-top: -5px;\r\n [if bg_type_1 == \'color\']\r\n background: [bg_color_1] 100%;\r\n box-shadow: -4px -4px 0px rgba(0, 0, 0, 0.1) inset;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 30px;\r\n text-shadow: 1px 1px 1px #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1) inset;\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 90%;\r\n font-family: \'PT Sans\', sans-serif;\r\n color: [bg_color_1];\r\n font-size: 25px;\r\n line-height: 25px;\r\n display: block;\r\n margin-bottom: 27px;\r\n padding: 0px 20px 0px 20px;\r\n text-align: center;\r\n}\r\n\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: -5px !important;\r\n right: -10px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n margin-top:20px;\r\n}\r\n.ppsPopupShell .ppsErrorMsg{\r\n width: 200px;\r\n}\r\n\r\n","highlights.png","1","1","1","1","2015-01-10 18:59:43","10"),
518
+ ("27","New York","1","0","YTozOntzOjQ6Im1haW4iO2E6MTc6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNzoic2hvd19vbl9zY3JvbGxfd2luZG93X2RlbGF5IjtzOjE6IjAiO3M6MzM6InNob3dfb25fc2Nyb2xsX3dpbmRvd19wZXJjX3Njcm9sbCI7czoxOiIwIjtzOjI4OiJzaG93X29uX2FmdGVyX2luYWN0aXZlX3ZhbHVlIjtzOjI6IjEwIjtzOjg6ImNsb3NlX29uIjtzOjEwOiJ1c2VyX2Nsb3NlIjtzOjI1OiJjbG9zZV9vbl9hZnRlcl90aW1lX3ZhbHVlIjtzOjE6IjUiO3M6MTA6InNob3dfcGFnZXMiO3M6MzoiYWxsIjtzOjc6InNob3dfdG8iO3M6ODoiZXZlcnlvbmUiO3M6Mjk6InNob3dfdG9fZmlyc3RfdGltZV92aXNpdF9kYXlzIjtzOjI6IjMwIjtzOjMwOiJzaG93X3RvX3VudGlsX21ha2VfYWN0aW9uX2RheXMiO3M6MjoiMzAiO3M6MjE6ImhpZGVfZm9yX2RldmljZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX2Zvcl9wb3N0X3R5cGVzX3Nob3ciO3M6MToiMCI7czoxNzoiaGlkZV9mb3JfaXBzX3Nob3ciO3M6MToiMCI7czoxMjoiaGlkZV9mb3JfaXBzIjtzOjA6IiI7czoyMzoiaGlkZV9mb3JfY291bnRyaWVzX3Nob3ciO3M6MToiMCI7czoyMzoiaGlkZV9mb3JfbGFuZ3VhZ2VzX3Nob3ciO3M6MToiMCI7fXM6MzoidHBsIjthOjU5OntzOjU6IndpZHRoIjtzOjM6IjgyNCI7czoxMzoid2lkdGhfbWVhc3VyZSI7czoyOiJweCI7czoxODoiYmdfb3ZlcmxheV9vcGFjaXR5IjtzOjM6IjAuNSI7czo5OiJiZ190eXBlXzAiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzAiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6OToiYmdfdHlwZV8xIjtzOjU6ImNvbG9yIjtzOjg6ImJnX2ltZ18xIjtzOjA6IiI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjM2E4OWZmIjtzOjk6ImJnX3R5cGVfMiI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMiI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzIiO3M6NzoiI2U4ZDA0NyI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiMzYTg5ZmYiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiIzg4ODg4OCI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzU4NTg1OCI7czo5OiJjbG9zZV9idG4iO3M6MTE6IndoaWxlX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTI6ImNpcmNsZV9ncmVlbiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjEzOiJTVUJTQ1JJQkUgTk9XIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6NjY6IlNVQlNDUklCRSBUTyBPVVIgTkVXU0xFVFRFUiBBTkQgU1RBUlQgSU5DUkVBU0lORyBZT1VSIFBST0ZJVFMgTk9XISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czoxMzoiZW5iX2Zvb3Rfbm90ZSI7czoxOiIxIjtzOjk6ImZvb3Rfbm90ZSI7czo0NzoiKiB3ZSBuZXZlciBzaGFyZSB5b3VyIGUtbWFpbCB3aXRoIHRoaXJkIHBhcnRpZXMiO3M6NToidHh0XzAiO3M6NDg6IjxwPltnb29nbGVfbWFwX2Vhc3kgaWQ9XCIxXCIgaGVpZ2h0PVwiMzAwXCJdPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMyI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<link rel=\"stylesheet\" type=\"text/css\" href=\"//fonts.googleapis.com/css?family=Didact+Gothic\" />\r\n<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n </div>\r\n <div class=\"ppsRightCol\">\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n <div style=\"clear: both;\"></div>\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","@nice-blue: #5B83AD;\r\n#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: block;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 60%;\r\n box-shadow: rgba(32,32,32,1) 0 4px 20px;\r\n border-radius:3px;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: block;\r\n float: left;\r\n margin-top: 30px;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\ncolor:#ffffff;\r\n font-family: \'Didact Gothic\';\r\n font-weight: 700;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 25px;\r\n padding-left: 20px;\r\n letter-spacing: -1px;\r\n text-align: center;\r\n line-height: 1.475;\r\n [if enb_txt_0]\r\n width: 95;\r\n [else]\r\n width: 95%;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsRightCol {\r\n display: table-cell;\r\n border-radius:3px;\r\n min-height: 350px;\r\n width: 40%;\r\n height: 110%;\r\n display: block;\r\n float: right;\r\n box-shadow: rgba(32,32,32,1) 0 4px 20px;\r\n padding: 10px 0;\r\n [if bg_type_1 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}), color-stop(100%, [bg_color_1])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }} 0%, [bg_color_1] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_1, 50) }}\', endColorstr=\'[bg_color_1]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n width: 100%;\r\n margin-bottom: 10px;\r\n height: 40px;\r\n border: 1px solid #d1b36d;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 2px 2px 2px #dcdcdc inset;\r\n padding-left: 22px;\r\n font-size: 17px;\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/user-black-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n border-radius: 2px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n background-color: #fff;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text][name=\"email\"] {\r\n background-image: url(\"[PPS_ASSETS_URL]img/assets/email-black-icon.png\");\r\n background-repeat: no-repeat;\r\n background-position: 5px center;\r\n border-radius: 2px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n font-family: \'Didact Gothic\';\r\n [if bg_type_2 == \'color\']\r\n background: [bg_color_2];\r\n \r\n [elseif bg_type_2 == \'img\']\r\n background-image: url(\"[bg_img_2]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n \r\n color: #fff;\r\n font-size: 20px;\r\n text-shadow: 1px 2px 1px #000;\r\n cursor: pointer;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 100%;\r\n height: 300px;\r\n color: #888888;\r\n font-family: \'arial\', arial;\r\n font-weight: 400;\r\n line-height: 1.3;\r\n font-size: 14px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_1 {\r\n color:#ffffff;\r\n font-family: \'arial\', arial;\r\n font-weight: 700;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 25px;\r\n padding-left: 20px;\r\n letter-spacing: -1px;\r\n text-align: center;\r\n line-height: 1.475;\r\n [if enb_txt_0]\r\n width: 95;\r\n [else]\r\n width: 95%;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top:-20px;\r\n right:1px;\r\n z-index:99999;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}\r\n\r\n#ppsPopupShell_[ID] p{\r\nmargin-left:20px;\r\n}\r\n#ppsPopupShell_[ID] b{\r\ncolor: #000;\r\n}\r\n#ppsPopupShell_[ID] ul li {\r\nheight:30px;\r\n}","newyork.png","1","1","1","1","2015-01-10 18:59:43","28"),
519
+ ("28","Smart","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6OTQ6e3M6NToid2lkdGgiO3M6MzoiNzcwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czozOiJpbWciO3M6ODoiYmdfaW1nXzAiO3M6NDM6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2JnLWZvcm0tbWFpbi5wbmciO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiIzNkODJiZiI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6Mzk6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2J1dHRvbi0xLnBuZyI7czoxMDoiYmdfY29sb3JfMSI7czo3OiIjZmZmZmZmIjtzOjk6ImJnX3R5cGVfMiI7czozOiJpbWciO3M6ODoiYmdfaW1nXzIiO3M6NDA6IltQUFNfQVNTRVRTX1VSTF1pbWcvYXNzZXRzL2Zvcm0tYm9vay5wbmciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2VlZWUyMiI7czoxMDoiZm9udF9sYWJlbCI7czo3OiJkZWZhdWx0IjtzOjE2OiJsYWJlbF9mb250X2NvbG9yIjtzOjc6IiNmZjQ0MTEiO3M6MTA6ImZvbnRfdHh0XzAiO3M6NzoiZGVmYXVsdCI7czoxNzoidGV4dF9mb250X2NvbG9yXzAiO3M6NzoiIzAwMDAwMCI7czoxMToiZm9udF9mb290ZXIiO3M6NzoiZGVmYXVsdCI7czoxNzoiZm9vdGVyX2ZvbnRfY29sb3IiO3M6NzoiIzk3OTY5NiI7czoxNToicmVzcG9uc2l2ZV9tb2RlIjtzOjM6ImRlZiI7czoxNzoicmVpZHJlY3Rfb25fY2xvc2UiO3M6MDoiIjtzOjk6ImNsb3NlX2J0biI7czoxMToiY2xhc3N5X2dyZXkiO3M6NzoiYnVsbGV0cyI7czo0OiJ0aWNrIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6NTc6IkdldCBpdCBOT1chIEluY3JlYXNlIG1vcmUgdGhhbiA3MDAlIG9mIEVtYWlsIFN1YnNjcmliZXJzISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE3OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUiO3M6MTU6ImVuYl9zbV9mYWNlYm9vayI7czoxOiIxIjtzOjE3OiJlbmJfc21fZ29vZ2xlcGx1cyI7czoxOiIxIjtzOjE0OiJlbmJfc21fdHdpdHRlciI7czoxOiIxIjtzOjk6InNtX2Rlc2lnbiI7czo2OiJzaW1wbGUiO3M6ODoiYW5pbV9rZXkiO3M6MTQ6InBlcnNwZWN0aXZlX3VwIjtzOjEzOiJhbmltX2R1cmF0aW9uIjtzOjA6IiI7czoxMzoiZW5iX3N1YnNjcmliZSI7czoxOiIxIjtzOjg6InN1Yl9kZXN0IjtzOjk6IndvcmRwcmVzcyI7czoyMzoic3ViX3dwX2NyZWF0ZV91c2VyX3JvbGUiO3M6MTA6InN1YnNjcmliZXIiO3M6MTk6InN1Yl9hd2ViZXJfbGlzdG5hbWUiO3M6MDoiIjtzOjIxOiJzdWJfYXdlYmVyX2FkdHJhY2tpbmciO3M6MDoiIjtzOjIxOiJzdWJfbWFpbGNoaW1wX2FwaV9rZXkiO3M6MDoiIjtzOjI1OiJzdWJfbWFpbGNoaW1wX2dyb3Vwc19mdWxsIjtzOjA6IiI7czoxNDoic3ViX2dyX2FwaV9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfZ3JfY3ljbGVfZGF5IjtzOjE6IjAiO3M6MTM6InN1Yl9pY19hcHBfaWQiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3VzZXIiO3M6MDoiIjtzOjE1OiJzdWJfaWNfYXBwX3Bhc3MiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX3VybCI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfa2V5IjtzOjA6IiI7czoxODoic3ViX2FyX2Zvcm1fYWN0aW9uIjtzOjA6IiI7czoxMDoic3ViX3NnYV9pZCI7czowOiIiO3M6MTU6InN1Yl9zZ2FfbGlzdF9pZCI7czowOiIiO3M6MjE6InN1Yl9zZ2FfYWN0aXZhdGVfY29kZSI7czowOiIiO3M6MTM6InN1Yl9zZl9hcHBfaWQiO3M6MDoiIjtzOjE0OiJzdWJfY2tfYXBpX2tleSI7czowOiIiO3M6MTQ6InN1Yl9tZW1fYWNjX2lkIjtzOjA6IiI7czoxNToic3ViX21lbV9wdWRfa2V5IjtzOjA6IiI7czoxNjoic3ViX21lbV9wcml2X2tleSI7czowOiIiO3M6MTA6InN1Yl9maWVsZHMiO2E6Mjp7czo0OiJuYW1lIjthOjY6e3M6NDoibmFtZSI7czo0OiJuYW1lIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo0OiJOYW1lIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMCI7fXM6NToiZW1haWwiO2E6Nzp7czo0OiJuYW1lIjtzOjU6ImVtYWlsIjtzOjQ6Imh0bWwiO3M6NDoidGV4dCI7czo1OiJsYWJlbCI7czo2OiJFLU1haWwiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIxIjtzOjM6ImVuYiI7czoxOiIxIjt9fXM6MjA6InN1Yl90eHRfY29uZmlybV9zZW50IjtzOjY3OiJDb25maXJtYXRpb24gbGluayB3YXMgc2VudCB0byB5b3VyIGVtYWlsIGFkZHJlc3MuIENoZWNrIHlvdXIgZW1haWwhIjtzOjE1OiJzdWJfdHh0X3N1Y2Nlc3MiO3M6MjQ6IlRoYW5rIHlvdSBmb3Igc3Vic2NyaWJlISI7czoyMToic3ViX3R4dF9pbnZhbGlkX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjIwOiJzdWJfdHh0X2V4aXN0c19lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoic3ViX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gc3Vic2NyaXB0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InN1Yl90eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NzoiWW91IHN1YnNjcmliZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgc3Vic2NyaXB0aW9uLiBJZiB5b3UgZGlkIG5vdCBzdWJzY3JpYmUgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoyNToic3ViX3JlZGlyZWN0X2VtYWlsX2V4aXN0cyI7czowOiIiO3M6MTM6InN1Yl9idG5fbGFiZWwiO3M6MTE6IkdldCBpdCBub3chIjtzOjEzOiJzdWJfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToic3ViX25ld19tZXNzYWdlIjtzOjEyOToiWW91IGhhdmUgbmV3IHN1YnNjcmliZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBzdWJzY3JpYmVyIGluZm9ybWF0aW9uOjxiciAvPltzdWJzY3JpYmVyX2RhdGFdIjtzOjg6ImxvZ2luX2J5IjtzOjg6InVzZXJuYW1lIjtzOjE4OiJsb2dpbl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjE1OiJsb2dpbl9idG5fbGFiZWwiO3M6NToiTG9naW4iO3M6MjM6InJlZ193cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjEzOiJyZWdfYnRuX2xhYmVsIjtzOjg6IlJlZ2lzdGVyIjtzOjEwOiJyZWdfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo3OntzOjM6ImVuYiI7czoxOiIxIjtzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJyZWdfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToicmVnX3R4dF9zdWNjZXNzIjtzOjI3OiJUaGFuayB5b3UgZm9yIHJlZ2lzdHJhdGlvbiEiO3M6MjE6InJlZ190eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoxNjoicmVnX3JlZGlyZWN0X3VybCI7czowOiIiO3M6Mjg6InJlZ190eHRfY29uZmlybV9tYWlsX3N1YmplY3QiO3M6MzQ6IkNvbmZpcm0gcmVnaXN0cmF0aW9uIG9uIFtzaXRlbmFtZV0iO3M6MjU6InJlZ190eHRfY29uZmlybV9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9tZXNzYWdlIjtzOjE5NjoiWW91IHJlZ2lzdGVyZWQgb24gc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4uIEZvbGxvdyA8YSBocmVmPVwiW2NvbmZpcm1fbGlua11cIj50aGlzIGxpbms8L2E+IHRvIGNvbXBsZXRlIHlvdXIgcmVnaXN0cmF0aW9uLiBJZiB5b3UgZGlkIG5vdCByZWdpc3RlciBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoicmVnX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjEzOiJyZWdfbmV3X2VtYWlsIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoxNToicmVnX25ld19tZXNzYWdlIjtzOjEyMToiWW91IGhhdmUgbmV3IG1lbWJlciBvbiB5b3VyIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LCBoZXJlIHVzIG1lbWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo1OiJ0eHRfMCI7czoyMTQ6IjxwPlNtYXJ0IFBvcHVwIGl0IGlzIHRoZSBtb3N0IHBvd2VyZnVsIHBvcHVwIHN5c3RlbSBmb3IgV29yZFByZXNzIG9uIHRoZSBtYXJrZXQuIEl0IGNvbWJpbmVzIGEgcHJvZmVzc2lvbmFsbHkgZGVzaWduZWQgd2VsY29tZS9leGl0IHdpbmRvdyBzb2NpYWwgbG9ja2VyIGFuZCBzdWJzY3JpYmluZyBvcHQtaW4gc3lzdGVtIGZvciBzbWFydCBlLW1haWwgbWFya2V0aW5nLjwvcD4iO31zOjEwOiJvcHRzX2F0dHJzIjthOjI6e3M6OToiYmdfbnVtYmVyIjtzOjE6IjQiO3M6MTY6InR4dF9ibG9ja19udW1iZXIiO3M6MToiMSI7fX0=","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose\"></a>\r\n <div class=\"ppsPopupListsInner\">\r\n <div class=\"ppsPopupTblCols\">\r\n <div class=\"ppsPopupLeftCol\">\r\n [if bg_type_2 == \'img\']\r\n <img src=\"[bg_img_2]\" />\r\n [endif]\r\n </div>\r\n <div class=\"ppsPopupRightCol\">\r\n <div class=\"ppsBigArrow\"></div>\r\n [if enb_label]\r\n <div class=\"ppsPopupLabel\">[label]</div>\r\n [endif]\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupTxt_0\">[txt_0]</div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n font-family: Helvetica,Arial,sans-serif;\r\n font-size: 14px;\r\n [if bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID], #ppsPopupShell_[ID] * {\r\n -webkit-box-sizing: content-box;\r\n -moz-box-sizing: content-box;\r\n box-sizing: content-box;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: [bg_color_1];\r\n font-size: 25px;\r\n font-weight: bold;\r\n line-height: 1.2;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupListsInner {\r\n border: 3px solid #bac0ac;\r\n -webkit-box-shadow: inset 0 0 0 5px #fff, 0 10px 25px rgba(0,0,0,0.5);\r\n -moz-box-shadow: inset 0 0 0 5px #fff, 0 10px 25px rgba(0,0,0,0.5);\r\n box-shadow: inset 0 0 0 5px #fff, 0 10px 25px rgba(0,0,0,0.5);\r\n [if bg_type_0 == \'color\']\r\n background: {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}; /* Old browsers */\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* FF3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%,[bg_color_0])); /* Chrome,Safari4+ */\r\n background: -webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Chrome10+,Safari5.1+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* Opera 12+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* IE10+ */\r\n background: radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%,[bg_color_0] 100%); /* W3C */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'#eaeaea\',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 .ppsTxtContent {\r\n padding: 10px 10px 10px 50px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTblCols {\r\n display: table;\r\n padding: 10px 10px 10px 30px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLeftCol {\r\n display: table-cell;\r\n [if enb_subscribe]\r\n width: 30%;\r\n [else]\r\n width: 30%;\r\n min-height: 60%;\r\n [endif]\r\n vertical-align: middle;\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupRightCol {\r\n width: 70%;\r\n display: table-cell;\r\n border-radius: 8px;\r\n -moz-border-radius: 8px;\r\n -webkit-border-radius: 8px;\r\n margin: 8px 5px 5px 5px;\r\n text-align: left;\r\n padding: 30px 0 30px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n padding: 30px 0 0;\r\n text-align: center;\r\n position: relative;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n margin-bottom: 10px;\r\n height: 37px !important;\r\n width: 60%;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n box-shadow: 0px [bg_color_1] inset;\r\n padding: 0 0 0 10px;\r\n font-size: 17px;\r\n background: [bg_color_1];\r\n border: 1px solid transparent;\r\n color: #993300;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n margin-left: -15px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding: 20px 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email] {\r\n float: left;\r\n margin-left: 7px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n border: none;\r\n float:left;\r\n [if bg_type_3 == \'color\']\r\n background: [bg_color_3];\r\n background-image: none;\r\n [elseif bg_type_3 == \'img\']\r\n background-image: url(\"[bg_img_3]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #993300;;\r\n font-size: 17px;\r\n cursor: pointer;\r\n width: auto;\r\n text-transform: uppercase;\r\n -webkit-transition: all 0.5s ease;\r\n -moz-transition: all 0.5s ease;\r\n -o-transition: all 0.5s ease;\r\n transition: all 0.5s ease;\r\n padding: 1px 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n right: -5px;\r\n top: 2px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n float: left;\r\n width: 90%;\r\n font-family: \'PT Serif\', serif;\r\n color: #fff;\r\n font-size: 16px;\r\n line-height: 24px;\r\n display: block;\r\n margin-bottom: 27px;\r\n padding: 0px 20px 0px 0;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote {\r\n [if enb_subscribe]\r\n color: #000000;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [else]\r\n margin-top: 10px;\r\n color: #979696;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: xx-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n text-align: left;\r\n margin-left: 10px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsSm{\r\n[if enb_subscribe]\r\n [else]\r\n margin-top: 130px;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] li{\r\n font-weight: bold;\r\n font-size: 13px;\r\n padding-top: 3px;\r\n padding-bottom: 3px;\r\n color: #737E86;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubMsg {\r\n clear: both;\r\n}","smart.png","1","1","1","1","2015-01-13 19:22:48","14"),
520
+ ("29","Find Us","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6ODg6e3M6NToid2lkdGgiO3M6MzoiNjcwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo0OiJub25lIjtzOjg6ImJnX2ltZ18wIjtzOjE6ImgiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2VlZWUyMiI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiNkZDMzMzMiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjZmZmZmZmIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiNmZmZmZmYiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6IndoaWxlX2Nsb3NlIjtzOjc6ImJ1bGxldHMiO3M6MTE6Imxpc3RzX2dyZWVuIjtzOjExOiJsYXllcmVkX3BvcyI7czozOiJ0b3AiO3M6OToiZW5iX2xhYmVsIjtzOjE6IjEiO3M6NToibGFiZWwiO3M6MTI6IkZpbmQgdXMgaGVyZSI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6Njoic2ltcGxlIjtzOjg6ImFuaW1fa2V5IjtzOjQ6Im5vbmUiO3M6MTM6ImFuaW1fZHVyYXRpb24iO3M6MDoiIjtzOjEzOiJlbmJfc3Vic2NyaWJlIjtzOjE6IjEiO3M6ODoic3ViX2Rlc3QiO3M6OToid29yZHByZXNzIjtzOjIzOiJzdWJfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxOToic3ViX2F3ZWJlcl9saXN0bmFtZSI7czowOiIiO3M6MjE6InN1Yl9hd2ViZXJfYWR0cmFja2luZyI7czowOiIiO3M6MjE6InN1Yl9tYWlsY2hpbXBfYXBpX2tleSI7czowOiIiO3M6MjU6InN1Yl9tYWlsY2hpbXBfZ3JvdXBzX2Z1bGwiO3M6MDoiIjtzOjE0OiJzdWJfZ3JfYXBpX2tleSI7czowOiIiO3M6MTY6InN1Yl9ncl9jeWNsZV9kYXkiO3M6MToiMCI7czoxMzoic3ViX2ljX2FwcF9pZCI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfdXNlciI7czowOiIiO3M6MTU6InN1Yl9pY19hcHBfcGFzcyI7czowOiIiO3M6MTQ6InN1Yl9hY19hcGlfdXJsIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV9rZXkiO3M6MDoiIjtzOjE4OiJzdWJfYXJfZm9ybV9hY3Rpb24iO3M6MDoiIjtzOjEwOiJzdWJfc2dhX2lkIjtzOjA6IiI7czoxNToic3ViX3NnYV9saXN0X2lkIjtzOjA6IiI7czoyMToic3ViX3NnYV9hY3RpdmF0ZV9jb2RlIjtzOjA6IiI7czoxMzoic3ViX3NmX2FwcF9pZCI7czowOiIiO3M6MTQ6InN1Yl9ja19hcGlfa2V5IjtzOjA6IiI7czoxNDoic3ViX21lbV9hY2NfaWQiO3M6MDoiIjtzOjE1OiJzdWJfbWVtX3B1ZF9rZXkiO3M6MDoiIjtzOjE2OiJzdWJfbWVtX3ByaXZfa2V5IjtzOjA6IiI7czoxMDoic3ViX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoic3ViX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InN1Yl90eHRfc3VjY2VzcyI7czoyNDoiVGhhbmsgeW91IGZvciBzdWJzY3JpYmUhIjtzOjIxOiJzdWJfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MjA6InN1Yl90eHRfZXhpc3RzX2VtYWlsIjtzOjIyOiJFbXB0eSBvciBpbnZhbGlkIGVtYWlsIjtzOjE2OiJzdWJfcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfc3ViamVjdCI7czozNDoiQ29uZmlybSBzdWJzY3JpcHRpb24gb24gW3NpdGVuYW1lXSI7czoyNToic3ViX3R4dF9jb25maXJtX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6Mjg6InN1Yl90eHRfY29uZmlybV9tYWlsX21lc3NhZ2UiO3M6MTk3OiJZb3Ugc3Vic2NyaWJlZCBvbiBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPi4gRm9sbG93IDxhIGhyZWY9XCJbY29uZmlybV9saW5rXVwiPnRoaXMgbGluazwvYT4gdG8gY29tcGxldGUgeW91ciBzdWJzY3JpcHRpb24uIElmIHlvdSBkaWQgbm90IHN1YnNjcmliZSBoZXJlIC0ganVzdCBpZ25vcmUgdGhpcyBtZXNzYWdlLiI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfc3ViamVjdCI7czozNzoiW3NpdGVuYW1lXSBZb3VyIHVzZXJuYW1lIGFuZCBwYXNzd29yZCI7czoyODoic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfZnJvbSI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MzE6InN1Yl90eHRfc3Vic2NyaWJlcl9tYWlsX21lc3NhZ2UiO3M6NjU6IlVzZXJuYW1lOiBbdXNlcl9sb2dpbl08YnIgLz5QYXNzd29yZDogW3Bhc3N3b3JkXTxiciAvPltsb2dpbl91cmxdIjtzOjI1OiJzdWJfcmVkaXJlY3RfZW1haWxfZXhpc3RzIjtzOjA6IiI7czoxMzoic3ViX2J0bl9sYWJlbCI7czo4OiJTaWduLXVwISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgdXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo4OiJsb2dpbl9ieSI7czo4OiJ1c2VybmFtZSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjU6IkxvZ2luIjtzOjIzOiJyZWdfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxMzoicmVnX2J0bl9sYWJlbCI7czo4OiJSZWdpc3RlciI7czoxMDoicmVnX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czoyNzoiVGhhbmsgeW91IGZvciByZWdpc3RyYXRpb24hIjtzOjIxOiJyZWdfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InJlZ19yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHJlZ2lzdHJhdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTY6IllvdSByZWdpc3RlcmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHJlZ2lzdHJhdGlvbi4gSWYgeW91IGRpZCBub3QgcmVnaXN0ZXIgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZWdfdHh0X3N1YnNjcmliZXJfbWFpbF9tZXNzYWdlIjtzOjY1OiJVc2VybmFtZTogW3VzZXJfbG9naW5dPGJyIC8+UGFzc3dvcmQ6IFtwYXNzd29yZF08YnIgLz5bbG9naW5fdXJsXSI7czoxMzoicmVnX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InJlZ19uZXdfbWVzc2FnZSI7czoxMjE6IllvdSBoYXZlIG5ldyBtZW1iZXIgb24geW91ciBzaXRlIDxhIGhyZWY9XCJbc2l0ZXVybF1cIj5bc2l0ZW5hbWVdPC9hPiwgaGVyZSB1cyBtZW1iZXIgaW5mb3JtYXRpb246PGJyIC8+W3N1YnNjcmliZXJfZGF0YV0iO3M6NToidHh0XzAiO3M6MzM6IjxwPltnb29nbGVfbWFwX2Vhc3kgaWQ9XCIxXCJdPC9wPiI7fXM6MTA6Im9wdHNfYXR0cnMiO2E6Mjp7czo5OiJiZ19udW1iZXIiO3M6MToiMiI7czoxNjoidHh0X2Jsb2NrX251bWJlciI7czoxOiIxIjt9fQ==","<div id=\"ppsPopupShell_[ID]\" class=\"ppsPopupShell ppsPopupListsShell\">\r\n <a href=\"#\" class=\"ppsPopupClose ppsPopupClose_[close_btn]\"></a>\r\n <div class=\"ppsInnerTblContent\">\r\n <div class=\"ppsPopupListsInner ppsPopupInner\">\r\n [if enb_txt_0]\r\n <div class=\"ppsPopupTxt ppsPopupClassyTxt ppsPopupClassyTxt_0 ppsPopupTxt_0\">\r\n [txt_0]\r\n </div>\r\n [endif]\r\n [if enb_label]\r\n <div class=\"label-window\">\r\n <div class=\"ppsPopupLabel ppsPopupListsLabel\">[label]</div>\r\n </div>\r\n [endif]\r\n [if enb_subscribe]\r\n <div class=\"find-form ppsSubscribeShell\">\r\n [sub_form_start]\r\n [sub_fields_html]\r\n <input type=\"submit\" name=\"submit\" value=\"[sub_btn_label]\" />\r\n [sub_form_end]\r\n </div>\r\n [endif]\r\n <div style=\"clear: both;\"></div>\r\n [if enb_sm]\r\n <div class=\"ppsSm\">\r\n [sm_html]\r\n </div>\r\n [endif]\r\n [if enb_foot_note]\r\n <div class=\"ppsFootNote\">\r\n [foot_note]\r\n </div>\r\n [endif]\r\n </div>\r\n </div>\r\n</div>","#ppsPopupShell_[ID] {\r\n width: [width][width_measure];\r\n padding: 15px;\r\n font-family: Georgia, Times, serif;\r\n font-size: 13px;\r\n line-height: 21px;\r\n font-weight: normal;\r\n color: #000;\r\n}\r\n#ppsPopupShell_[ID] .ppsInnerTblContent {\r\n display: table;\r\n position: relative;\r\n [if bg_type_0 == \'color\']\r\n background: -moz-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ff3.6+ */\r\n background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}), color-stop(100%, [bg_color_0])); /* safari4+,chrome */\r\n background:-webkit-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* safari5.1+,chrome10+ */\r\n background: -o-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* opera 11.10+ */\r\n background: -ms-radial-gradient(center, ellipse cover, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* ie10+ */\r\n background:radial-gradient(ellipse at center, {{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }} 0%, [bg_color_0] 100%); /* w3c */\r\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr=\'{{ adjust_brightness(popup.params.tpl.bg_color_0, 50) }}\', endColorstr=\'[bg_color_0]\',GradientType=1 ); /* ie6-9 */\r\n [elseif bg_type_0 == \'img\']\r\n background-image: url(\"[bg_img_0]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupInner {\r\n position: relative;\r\n {% if popup.params.tpl.enb_subscribe or popup.params.tpl.enb_foot_note or popup.params.tpl.enb_sm %}\r\n width: 50%;\r\n [else]\r\n width: 100%;\r\n [endif]\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .label-window{\r\n position:absolute;\r\n top: 0;\r\n background-color: rgba(10,10,10,0.6);\r\n padding-right: 30px;\r\n left: 40px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupLabel {\r\n color: #000;\r\n font-family: \'Open Sans\', arial;\r\n font-size: 28px;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n margin-top: 15px;\r\n margin-bottom: 16px;\r\n padding-left: 20px;\r\n line-height: 26px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell {\r\n bottom: 20px;\r\n right: 20px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell form {\r\n text-align: center;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n padding: 11px 24px 10px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=text],#ppsPopupShell_[ID] .ppsSubscribeShell input[type=email],\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n /*background-color: rgba(0,0,0,0.8) !important;\r\n padding-left: 10px;\r\n font-size: 17px;\r\n color: #fff;*/\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelect {\r\n display: table;\r\n text-align: left;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel,\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n display: table-cell;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell .ppsSubSelectLabel {\r\n opacity: 0.5;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell select {\r\n width: 100%;\r\n background-color: transparent;\r\n height: 40px;\r\n border: none;\r\n font-size: 17px;\r\n color: #fff;\r\n border-top-right-radius: 3px;\r\n border-bottom-right-radius: 3px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell textarea {\r\n font-family: inherit;\r\n height: auto;\r\n padding-top: 5px;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit] {\r\n [if bg_type_1 == \'color\']\r\n background-color: [bg_color_1];\r\n background-image: none;\r\n [elseif bg_type_1 == \'img\']\r\n background-image: url(\"[bg_img_1]\");\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n [endif]\r\n color: #fff;\r\n cursor: pointer;\r\n border: none;\r\n}\r\n#ppsPopupShell_[ID] .ppsSubscribeShell input[type=submit]:hover {\r\n box-shadow: inset 1px 1px 3px #666;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n text-align: center;\r\n font-family: \'Open Sans\', arial;\r\n font-weight: 100;\r\n color: #ffffff;\r\n text-shadow: #000000 1px 1px 1px;\r\n font-size: 14px;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupTxt_0 {\r\n position:reletive;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose {\r\n background-repeat: no-repeat;\r\n cursor: pointer;\r\n top: -5px !important;\r\n right: -5px !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose.ppsPopupClose_lists_black {\r\n top: 0 !important;\r\n right: 0 !important;\r\n}\r\n#ppsPopupShell_[ID] .ppsPopupClose:hover {\r\n opacity: 0.8;\r\n}\r\n#ppsPopupShell_[ID] .ppsFootNote{\r\n color: #585858;\r\n font-family: \"Helvetica Neue\",Helvetica,Arial,sans-serif;\r\n font-size: x-small;\r\n font-style: italic;\r\n line-height: 14px;\r\n margin: 5px 30px;\r\n}","find-us.png","1","1","1","1","2015-01-10 18:59:43","29"),
521
+ ("30","Photodoto","1","0","YTozOntzOjQ6Im1haW4iO2E6Mjk6e3M6Nzoic2hvd19vbiI7czo5OiJwYWdlX2xvYWQiO3M6MjM6InNob3dfb25fcGFnZV9sb2FkX2RlbGF5IjtzOjA6IiI7czoyNToic2hvd19vbl9jbGlja19vbl9lbF9kZWxheSI7czoxOiIwIjtzOjI3OiJzaG93X29uX3Njcm9sbF93aW5kb3dfZGVsYXkiO3M6MToiMCI7czozMzoic2hvd19vbl9zY3JvbGxfd2luZG93X3BlcmNfc2Nyb2xsIjtzOjE6IjAiO3M6Mjg6InNob3dfb25fYWZ0ZXJfaW5hY3RpdmVfdmFsdWUiO3M6MjoiMTAiO3M6MjU6InNob3dfb25fbGlua19mb2xsb3dfZGVsYXkiO3M6MToiMCI7czo4OiJjbG9zZV9vbiI7czoxMDoidXNlcl9jbG9zZSI7czoyNjoiY2xvc2Vfb25fYWZ0ZXJfYWN0aW9uX3RpbWUiO3M6MToiMSI7czoyNToiY2xvc2Vfb25fYWZ0ZXJfdGltZV92YWx1ZSI7czoxOiI1IjtzOjEwOiJzaG93X3BhZ2VzIjtzOjM6ImFsbCI7czoxNDoic2hvd190aW1lX2Zyb20iO3M6NzoiMTI6MDBhbSI7czoxMjoic2hvd190aW1lX3RvIjtzOjc6IjEyOjAwYW0iO3M6MTQ6InNob3dfZGF0ZV9mcm9tIjtzOjA6IiI7czoxMjoic2hvd19kYXRlX3RvIjtzOjA6IiI7czo3OiJzaG93X3RvIjtzOjg6ImV2ZXJ5b25lIjtzOjI5OiJzaG93X3RvX2ZpcnN0X3RpbWVfdmlzaXRfZGF5cyI7czoyOiIzMCI7czozMDoic2hvd190b191bnRpbF9tYWtlX2FjdGlvbl9kYXlzIjtzOjI6IjMwIjtzOjE1OiJjb3VudF90aW1lc19udW0iO3M6MToiMSI7czoxNToiY291bnRfdGltZXNfbWVzIjtzOjM6ImRheSI7czoyMToiaGlkZV9mb3JfZGV2aWNlc19zaG93IjtzOjE6IjAiO3M6MjQ6ImhpZGVfZm9yX3Bvc3RfdHlwZXNfc2hvdyI7czoxOiIwIjtzOjE3OiJoaWRlX2Zvcl9pcHNfc2hvdyI7czoxOiIwIjtzOjEyOiJoaWRlX2Zvcl9pcHMiO3M6MDoiIjtzOjIzOiJoaWRlX2Zvcl9jb3VudHJpZXNfc2hvdyI7czoxOiIwIjtzOjIzOiJoaWRlX2Zvcl9sYW5ndWFnZXNfc2hvdyI7czoxOiIwIjtzOjI0OiJoaWRlX3NlYXJjaF9lbmdpbmVzX3Nob3ciO3M6MToiMCI7czoxODoiaGlkZV9wcmVnX3VybF9zaG93IjtzOjE6IjAiO3M6MTM6ImhpZGVfcHJlZ191cmwiO3M6MDoiIjt9czozOiJ0cGwiO2E6OTc6e3M6NToid2lkdGgiO3M6MzoiNjAwIjtzOjEzOiJ3aWR0aF9tZWFzdXJlIjtzOjI6InB4IjtzOjE4OiJiZ19vdmVybGF5X29wYWNpdHkiO3M6MzoiMC41IjtzOjk6ImJnX3R5cGVfMCI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMCI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzAiO3M6NzoiI2ZmZmZmZiI7czo5OiJiZ190eXBlXzEiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzEiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl8xIjtzOjc6IiM2OThjOGYiO3M6OToiYmdfdHlwZV8yIjtzOjM6ImltZyI7czo4OiJiZ19pbWdfMiI7czo0NDoiW1BQU19BU1NFVFNfVVJMXWltZy9hc3NldHMvcG9wX3N1YnNjcmliZS5qcGciO3M6MTA6ImJnX2NvbG9yXzIiO3M6MDoiIjtzOjk6ImJnX3R5cGVfMyI7czo1OiJjb2xvciI7czo4OiJiZ19pbWdfMyI7czowOiIiO3M6MTA6ImJnX2NvbG9yXzMiO3M6NzoiI2QyZWFlYSI7czo5OiJiZ190eXBlXzQiO3M6NToiY29sb3IiO3M6ODoiYmdfaW1nXzQiO3M6MDoiIjtzOjEwOiJiZ19jb2xvcl80IjtzOjc6IiNmMzNkMmUiO3M6MTA6ImZvbnRfbGFiZWwiO3M6NzoiZGVmYXVsdCI7czoxNjoibGFiZWxfZm9udF9jb2xvciI7czo3OiIjMDAwMDAwIjtzOjEwOiJmb250X3R4dF8wIjtzOjc6ImRlZmF1bHQiO3M6MTc6InRleHRfZm9udF9jb2xvcl8wIjtzOjc6IiMwMDAwMDAiO3M6MTE6ImZvbnRfZm9vdGVyIjtzOjc6ImRlZmF1bHQiO3M6MTc6ImZvb3Rlcl9mb250X2NvbG9yIjtzOjc6IiM1ODU4NTgiO3M6MTU6InJlc3BvbnNpdmVfbW9kZSI7czozOiJkZWYiO3M6MTc6InJlaWRyZWN0X29uX2Nsb3NlIjtzOjA6IiI7czo5OiJjbG9zZV9idG4iO3M6MTE6ImNsYXNzeV9ncmV5IjtzOjc6ImJ1bGxldHMiO3M6ODoicG9wX2ljb24iO3M6MTE6ImxheWVyZWRfcG9zIjtzOjM6InRvcCI7czo5OiJlbmJfbGFiZWwiO3M6MToiMSI7czo1OiJsYWJlbCI7czo1NToiU1RBUlQgTUFLSU5HIE1PTkVZIERPSU5HIFdIQVQgWU9VIExPVkU6IEZSRUUgT0YgQ09VUlNFISI7czo5OiJlbmJfdHh0XzAiO3M6MToiMSI7czo5OiJmb290X25vdGUiO3M6MTE4OiJXZSByZXNwZWN0IHlvdXIgcHJpdmFjeS4gWW91ciBpbmZvcm1hdGlvbiB3aWxsIG5vdCBiZSBzaGFyZWQgd2l0aCBhbnkgdGhpcmQgcGFydHkgYW5kIHlvdSBjYW4gdW5zdWJzY3JpYmUgYXQgYW55IHRpbWUgIjtzOjE1OiJlbmJfc21fZmFjZWJvb2siO3M6MToiMSI7czoxNzoiZW5iX3NtX2dvb2dsZXBsdXMiO3M6MToiMSI7czoxNDoiZW5iX3NtX3R3aXR0ZXIiO3M6MToiMSI7czo5OiJzbV9kZXNpZ24iO3M6NDoiYm94eSI7czo4OiJhbmltX2tleSI7czoxMDoic2xpZGVfZG93biI7czoxMzoiYW5pbV9kdXJhdGlvbiI7czowOiIiO3M6MTM6ImVuYl9zdWJzY3JpYmUiO3M6MToiMSI7czo4OiJzdWJfZGVzdCI7czo5OiJ3b3JkcHJlc3MiO3M6MjM6InN1Yl93cF9jcmVhdGVfdXNlcl9yb2xlIjtzOjEwOiJzdWJzY3JpYmVyIjtzOjE5OiJzdWJfYXdlYmVyX2xpc3RuYW1lIjtzOjA6IiI7czoyMToic3ViX2F3ZWJlcl9hZHRyYWNraW5nIjtzOjA6IiI7czoyMToic3ViX21haWxjaGltcF9hcGlfa2V5IjtzOjA6IiI7czoyNToic3ViX21haWxjaGltcF9ncm91cHNfZnVsbCI7czowOiIiO3M6MTQ6InN1Yl9ncl9hcGlfa2V5IjtzOjA6IiI7czoxNjoic3ViX2dyX2N5Y2xlX2RheSI7czoxOiIwIjtzOjEzOiJzdWJfaWNfYXBwX2lkIjtzOjA6IiI7czoxNToic3ViX2ljX2FwcF91c2VyIjtzOjA6IiI7czoxNToic3ViX2ljX2FwcF9wYXNzIjtzOjA6IiI7czoxNDoic3ViX2FjX2FwaV91cmwiO3M6MDoiIjtzOjE0OiJzdWJfYWNfYXBpX2tleSI7czowOiIiO3M6MTg6InN1Yl9hcl9mb3JtX2FjdGlvbiI7czowOiIiO3M6MTA6InN1Yl9zZ2FfaWQiO3M6MDoiIjtzOjE1OiJzdWJfc2dhX2xpc3RfaWQiO3M6MDoiIjtzOjIxOiJzdWJfc2dhX2FjdGl2YXRlX2NvZGUiO3M6MDoiIjtzOjEzOiJzdWJfc2ZfYXBwX2lkIjtzOjA6IiI7czoxNDoic3ViX2NrX2FwaV9rZXkiO3M6MDoiIjtzOjE0OiJzdWJfbWVtX2FjY19pZCI7czowOiIiO3M6MTU6InN1Yl9tZW1fcHVkX2tleSI7czowOiIiO3M6MTY6InN1Yl9tZW1fcHJpdl9rZXkiO3M6MDoiIjtzOjEwOiJzdWJfZmllbGRzIjthOjI6e3M6NDoibmFtZSI7YTo2OntzOjQ6Im5hbWUiO3M6NDoibmFtZSI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NDoiTmFtZSI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjAiO31zOjU6ImVtYWlsIjthOjc6e3M6NDoibmFtZSI7czo1OiJlbWFpbCI7czo0OiJodG1sIjtzOjQ6InRleHQiO3M6NToibGFiZWwiO3M6NjoiRS1NYWlsIjtzOjU6InZhbHVlIjtzOjA6IiI7czo2OiJjdXN0b20iO3M6MToiMCI7czo5OiJtYW5kYXRvcnkiO3M6MToiMSI7czozOiJlbmIiO3M6MToiMSI7fX1zOjIwOiJzdWJfdHh0X2NvbmZpcm1fc2VudCI7czo2NzoiQ29uZmlybWF0aW9uIGxpbmsgd2FzIHNlbnQgdG8geW91ciBlbWFpbCBhZGRyZXNzLiBDaGVjayB5b3VyIGVtYWlsISI7czoxNToic3ViX3R4dF9zdWNjZXNzIjtzOjI0OiJUaGFuayB5b3UgZm9yIHN1YnNjcmliZSEiO3M6MjE6InN1Yl90eHRfaW52YWxpZF9lbWFpbCI7czoyMjoiRW1wdHkgb3IgaW52YWxpZCBlbWFpbCI7czoyMDoic3ViX3R4dF9leGlzdHNfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InN1Yl9yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHN1YnNjcmlwdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJzdWJfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoic3ViX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTc6IllvdSBzdWJzY3JpYmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHN1YnNjcmlwdGlvbi4gSWYgeW91IGRpZCBub3Qgc3Vic2NyaWJlIGhlcmUgLSBqdXN0IGlnbm9yZSB0aGlzIG1lc3NhZ2UuIjtzOjMxOiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9zdWJqZWN0IjtzOjM3OiJbc2l0ZW5hbWVdIFlvdXIgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIjtzOjI4OiJzdWJfdHh0X3N1YnNjcmliZXJfbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czozMToic3ViX3R4dF9zdWJzY3JpYmVyX21haWxfbWVzc2FnZSI7czo2NToiVXNlcm5hbWU6IFt1c2VyX2xvZ2luXTxiciAvPlBhc3N3b3JkOiBbcGFzc3dvcmRdPGJyIC8+W2xvZ2luX3VybF0iO3M6MjU6InN1Yl9yZWRpcmVjdF9lbWFpbF9leGlzdHMiO3M6MDoiIjtzOjEzOiJzdWJfYnRuX2xhYmVsIjtzOjIwOiIgSSBXQU5UIFRISVMgQ09VUlNFISI7czoxMzoic3ViX25ld19lbWFpbCI7czoxNDoiYWRtaW5AbWFpbC5jb20iO3M6MTU6InN1Yl9uZXdfbWVzc2FnZSI7czoxMjk6IllvdSBoYXZlIG5ldyBzdWJzY3JpYmVyIG9uIHlvdXIgc2l0ZSA8YSBocmVmPVwiW3NpdGV1cmxdXCI+W3NpdGVuYW1lXTwvYT4sIGhlcmUgaXMgc3Vic2NyaWJlciBpbmZvcm1hdGlvbjo8YnIgLz5bc3Vic2NyaWJlcl9kYXRhXSI7czo4OiJsb2dpbl9ieSI7czo4OiJ1c2VybmFtZSI7czoxODoibG9naW5fcmVkaXJlY3RfdXJsIjtzOjA6IiI7czoxNToibG9naW5fYnRuX2xhYmVsIjtzOjU6IkxvZ2luIjtzOjIzOiJyZWdfd3BfY3JlYXRlX3VzZXJfcm9sZSI7czoxMDoic3Vic2NyaWJlciI7czoxMzoicmVnX2J0bl9sYWJlbCI7czo4OiJSZWdpc3RlciI7czoxMDoicmVnX2ZpZWxkcyI7YToyOntzOjQ6Im5hbWUiO2E6Nzp7czozOiJlbmIiO3M6MToiMSI7czo0OiJuYW1lIjtzOjQ6Im5hbWUiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjQ6Ik5hbWUiO3M6NToidmFsdWUiO3M6MDoiIjtzOjY6ImN1c3RvbSI7czoxOiIwIjtzOjk6Im1hbmRhdG9yeSI7czoxOiIwIjt9czo1OiJlbWFpbCI7YTo3OntzOjQ6Im5hbWUiO3M6NToiZW1haWwiO3M6NDoiaHRtbCI7czo0OiJ0ZXh0IjtzOjU6ImxhYmVsIjtzOjY6IkUtTWFpbCI7czo1OiJ2YWx1ZSI7czowOiIiO3M6NjoiY3VzdG9tIjtzOjE6IjAiO3M6OToibWFuZGF0b3J5IjtzOjE6IjEiO3M6MzoiZW5iIjtzOjE6IjEiO319czoyMDoicmVnX3R4dF9jb25maXJtX3NlbnQiO3M6Njc6IkNvbmZpcm1hdGlvbiBsaW5rIHdhcyBzZW50IHRvIHlvdXIgZW1haWwgYWRkcmVzcy4gQ2hlY2sgeW91ciBlbWFpbCEiO3M6MTU6InJlZ190eHRfc3VjY2VzcyI7czoyNzoiVGhhbmsgeW91IGZvciByZWdpc3RyYXRpb24hIjtzOjIxOiJyZWdfdHh0X2ludmFsaWRfZW1haWwiO3M6MjI6IkVtcHR5IG9yIGludmFsaWQgZW1haWwiO3M6MTY6InJlZ19yZWRpcmVjdF91cmwiO3M6MDoiIjtzOjI4OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9zdWJqZWN0IjtzOjM0OiJDb25maXJtIHJlZ2lzdHJhdGlvbiBvbiBbc2l0ZW5hbWVdIjtzOjI1OiJyZWdfdHh0X2NvbmZpcm1fbWFpbF9mcm9tIjtzOjE0OiJhZG1pbkBtYWlsLmNvbSI7czoyODoicmVnX3R4dF9jb25maXJtX21haWxfbWVzc2FnZSI7czoxOTY6IllvdSByZWdpc3RlcmVkIG9uIHNpdGUgPGEgaHJlZj1cIltzaXRldXJsXVwiPltzaXRlbmFtZV08L2E+LiBGb2xsb3cgPGEgaHJlZj1cIltjb25maXJtX2xpbmtdXCI+dGhpcyBsaW5rPC9hPiB0byBjb21wbGV0ZSB5b3VyIHJlZ2lzdHJhdGlvbi4gSWYgeW91IGRpZCBub3QgcmVnaXN0ZXIgaGVyZSAtIGp1c3QgaWdub3JlIHRoaXMgbWVzc2FnZS4iO3M6MzE6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX3N1YmplY3QiO3M6Mzc6IltzaXRlbmFtZV0gWW91ciB1c2VybmFtZSBhbmQgcGFzc3dvcmQiO3M6Mjg6InJlZ190eHRfc3Vic2NyaWJlcl9tYWlsX2Zyb20iO3M6MTQ6ImFkbWluQG1haWwuY29tIjtzOjMxOiJyZ