Version Description
- Fix an issue with registering custom taxonomies in WordPress 4.7.
- Implement an alternative escaping mechanism for custom format setting of the date field.
- types_render_shortcode() function and [types] shortcode now allows to use "id" attribute for $parent-post selection
- Exclude Media from post relationships since the current GUI isn't able to support it properly
- Fix exporting taxonomies with legacy "object_type" setting that was causing syntax errors in the output XML.
- Support all CPTs in Toolset Dashboard.
- Change the way we store the context of a Types field for string translation (use field group name instead of ID)
- Fix a WordPress 4.7 compatibility issue with direct access to $wp_filter.
- Make the manipulation with repetitive user field values more similar to post fields. Fix a front-end notice when there is only one value in a repeating user Skype field.
- Add missing mandatory URL validation to file fields.
- Add PHP template example files.
- Fix an issue with Types export and non-latin characters in a field group slug.
Download this release
Release Info
Developer | jadpm |
Plugin | Toolset Types – Custom Post Types, Custom Fields and Taxonomies |
Version | 2.2.4 |
Comparing to | |
See all releases |
Code changes from version 2.2.3 to 2.2.4
- application/controllers/field/utils.php +24 -0
- application/controllers/utils.php +9 -9
- application/functions.php +1 -1
- application/models/wpml/field/group/string.php +193 -0
- application/models/wpml/field/group/string/description.php +15 -0
- application/models/wpml/field/group/string/name.php +16 -0
- application/models/wpml/field_group.php +90 -0
- application/models/wpml/interface.php +6 -0
- examples/author.php +87 -0
- examples/content-book.php +101 -0
- examples/content-consultant.php +83 -0
- examples/content-house.php +131 -0
- examples/content-writer.php +88 -0
- examples/single-consultant.php +129 -0
- library/otgs/installer/changelog.txt +150 -142
- library/otgs/installer/includes/class-installer-dependencies.php +278 -278
- library/otgs/installer/includes/class-installer-theme.php +978 -978
- library/otgs/installer/includes/installer-api.php +115 -115
- library/otgs/installer/includes/installer-upgrader-skins.php +36 -36
- library/otgs/installer/includes/installer.class.php +2672 -2579
- library/otgs/installer/includes/translation-service-info.class.php +39 -39
- library/otgs/installer/installer.php +21 -21
- library/otgs/installer/loader.php +150 -150
- library/otgs/installer/locale/orig/installer.po +230 -230
- library/otgs/installer/repositories.xml +13 -13
- library/otgs/installer/res/css/admin.css +200 -192
- library/otgs/installer/res/js/admin.js +416 -402
- library/otgs/installer/res/js/iframeResizer.min.js +10 -10
- library/otgs/installer/res/js/installer_theme_install.js +96 -96
- library/otgs/installer/templates/downloads-list-compact.php +80 -80
- library/otgs/installer/templates/downloads-list.php +85 -85
- library/otgs/installer/templates/products-compact.php +147 -129
- library/otgs/installer/templates/repository-listing.php +196 -179
- library/toolset/types/embedded/frontend.php +41 -36
- library/toolset/types/embedded/includes/api.php +4 -3
- library/toolset/types/embedded/includes/custom-taxonomies.php +111 -83
- library/toolset/types/embedded/includes/fields-post.php +12 -10
- library/toolset/types/embedded/includes/fields.php +58 -0
- library/toolset/types/embedded/includes/fields/wysiwyg.php +23 -4
- library/toolset/types/embedded/includes/module-manager.php +42 -26
- library/toolset/types/embedded/includes/post-relationship.php +119 -44
- library/toolset/types/embedded/includes/usermeta-post.php +12 -7
- library/toolset/types/embedded/includes/wpml.php +4 -9
- library/toolset/types/embedded/resources/css/basic.css +5 -0
- library/toolset/types/embedded/resources/js/post-relationship.js +103 -84
- library/toolset/types/embedded/usermeta-init.php +8 -146
- library/toolset/types/includes/fields.php +18 -4
- library/toolset/types/includes/post-relationship.php +67 -53
- library/twig/twig/.travis.yml +7 -2
- library/twig/twig/CHANGELOG +51 -0
- library/twig/twig/doc/advanced.rst +118 -33
- library/twig/twig/doc/advanced_legacy.rst +5 -7
- library/twig/twig/doc/api.rst +46 -8
- library/twig/twig/doc/deprecated.rst +51 -3
- library/twig/twig/doc/filters/date.rst +6 -0
- library/twig/twig/doc/filters/escape.rst +3 -0
- library/twig/twig/doc/filters/number_format.rst +3 -0
- library/twig/twig/doc/functions/block.rst +26 -0
- library/twig/twig/doc/functions/constant.rst +11 -0
- library/twig/twig/doc/functions/date.rst +3 -0
- library/twig/twig/doc/functions/include.rst +7 -3
- library/twig/twig/doc/internals.rst +5 -1
- library/twig/twig/doc/recipes.rst +53 -3
- library/twig/twig/doc/tags/autoescape.rst +0 -2
- library/twig/twig/doc/tags/embed.rst +4 -4
- library/twig/twig/doc/tags/extends.rst +6 -2
- library/twig/twig/doc/tags/include.rst +7 -3
- library/twig/twig/doc/tags/index.rst +1 -0
- library/twig/twig/doc/tags/with.rst +44 -0
- library/twig/twig/doc/templates.rst +2 -4
- library/twig/twig/doc/tests/empty.rst +0 -1
- library/twig/twig/ext/twig/php_twig.h +1 -1
- library/twig/twig/ext/twig/twig.c +22 -22
- library/twig/twig/lib/Twig/BaseNodeVisitor.php +0 -6
- library/twig/twig/lib/Twig/Compiler.php +22 -28
- library/twig/twig/lib/Twig/CompilerInterface.php +1 -3
- library/twig/twig/lib/Twig/Environment.php +204 -93
- library/twig/twig/lib/Twig/Error.php +49 -18
- library/twig/twig/lib/Twig/ExpressionParser.php +120 -32
- library/twig/twig/lib/Twig/Extension.php +10 -0
- library/twig/twig/lib/Twig/Extension/Core.php +59 -104
- library/twig/twig/lib/Twig/Extension/Escaper.php +10 -6
- library/twig/twig/lib/Twig/Extension/Profiler.php +1 -1
- library/twig/twig/lib/Twig/Extension/StringLoader.php +1 -1
- library/twig/twig/lib/Twig/ExtensionInterface.php +3 -3
- library/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php +7 -7
- library/twig/twig/lib/Twig/Filter/Method.php +1 -1
- library/twig/twig/lib/Twig/Function/Method.php +1 -1
- library/twig/twig/lib/Twig/Lexer.php +13 -5
- library/twig/twig/lib/Twig/LexerInterface.php +4 -4
- library/twig/twig/lib/Twig/Loader/Array.php +17 -4
- library/twig/twig/lib/Twig/Loader/Chain.php +34 -10
- library/twig/twig/lib/Twig/Loader/Filesystem.php +57 -25
- library/twig/twig/lib/Twig/Loader/String.php +11 -1
- library/twig/twig/lib/Twig/LoaderInterface.php +2 -0
- library/twig/twig/lib/Twig/Node.php +40 -40
- library/twig/twig/lib/Twig/Node/CheckSecurity.php +3 -3
- library/twig/twig/lib/Twig/Node/Embed.php +7 -5
- library/twig/twig/lib/Twig/Node/Expression/Array.php +2 -2
- library/twig/twig/lib/Twig/Node/Expression/Binary/Power.php +4 -0
- library/twig/twig/lib/Twig/Node/Expression/BlockReference.php +59 -14
- library/twig/twig/lib/Twig/Node/Expression/Call.php +54 -18
- library/twig/twig/lib/Twig/Node/Expression/Filter/Default.php +4 -4
- library/twig/twig/lib/Twig/Node/Expression/Function.php +7 -2
- library/twig/twig/lib/Twig/Node/Expression/Name.php +14 -4
- library/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php +26 -3
- library/twig/twig/lib/Twig/Node/Expression/Test/Defined.php +6 -3
- library/twig/twig/lib/Twig/Node/Import.php +2 -2
- library/twig/twig/lib/Twig/Node/Include.php +2 -2
- library/twig/twig/lib/Twig/Node/Macro.php +3 -3
- library/twig/twig/lib/Twig/Node/Module.php +51 -17
- library/twig/twig/lib/Twig/Node/Sandbox.php +1 -1
- library/twig/twig/lib/Twig/Node/SandboxedPrint.php +2 -4
- library/twig/twig/lib/Twig/Node/Set.php +1 -1
- library/twig/twig/lib/Twig/Node/With.php +62 -0
- library/twig/twig/lib/Twig/NodeInterface.php +3 -2
- library/twig/twig/lib/Twig/NodeTraverser.php +2 -11
- library/twig/twig/lib/Twig/NodeVisitor/Escaper.php +3 -3
- library/twig/twig/lib/Twig/NodeVisitor/Optimizer.php +9 -22
- library/twig/twig/lib/Twig/NodeVisitor/Sandbox.php +1 -1
- library/twig/twig/lib/Twig/NodeVisitorInterface.php +0 -6
- library/twig/twig/lib/Twig/Parser.php +37 -27
- library/twig/twig/lib/Twig/ParserInterface.php +1 -3
- library/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php +1 -1
- library/twig/twig/lib/Twig/RuntimeLoaderInterface.php +27 -0
- library/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php +38 -0
- library/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php +38 -0
- library/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php +4 -2
- library/twig/twig/lib/Twig/Source.php +49 -0
- library/twig/twig/lib/Twig/SourceContextLoaderInterface.php +31 -0
- library/twig/twig/lib/Twig/Template.php +158 -73
- library/twig/twig/lib/Twig/TemplateInterface.php +1 -1
- library/twig/twig/lib/Twig/TemplateWrapper.php +131 -0
- library/twig/twig/lib/Twig/Test/IntegrationTestCase.php +11 -5
- library/twig/twig/lib/Twig/Test/Method.php +1 -1
- library/twig/twig/lib/Twig/Test/NodeTestCase.php +4 -0
- library/twig/twig/lib/Twig/Token.php +7 -20
- library/twig/twig/lib/Twig/TokenParser.php +0 -2
- library/twig/twig/lib/Twig/TokenParser/AutoEscape.php +2 -2
- library/twig/twig/lib/Twig/TokenParser/Block.php +2 -2
- library/twig/twig/lib/Twig/TokenParser/Embed.php +1 -1
- library/twig/twig/lib/Twig/TokenParser/Extends.php +5 -3
- library/twig/twig/lib/Twig/TokenParser/Filter.php +1 -1
- library/twig/twig/lib/Twig/TokenParser/For.php +5 -5
- library/twig/twig/lib/Twig/TokenParser/From.php +1 -1
- library/twig/twig/lib/Twig/TokenParser/If.php +1 -1
- library/twig/twig/lib/Twig/TokenParser/Macro.php +1 -1
- library/twig/twig/lib/Twig/TokenParser/Sandbox.php +4 -3
- library/twig/twig/lib/Twig/TokenParser/Set.php +2 -2
- library/twig/twig/lib/Twig/TokenParser/Use.php +1 -1
- library/twig/twig/lib/Twig/TokenParser/With.php +48 -0
- library/twig/twig/lib/Twig/TokenParserBroker.php +0 -22
- library/twig/twig/lib/Twig/TokenParserBrokerInterface.php +1 -3
- library/twig/twig/lib/Twig/TokenParserInterface.php +1 -5
- library/twig/twig/lib/Twig/TokenStream.php +43 -20
- library/twig/twig/lib/Twig/Util/DeprecationCollector.php +2 -2
- library/twig/twig/phpunit.xml.dist +8 -0
- library/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php +1 -1
- library/twig/twig/test/Twig/Tests/EnvironmentTest.php +166 -38
- library/twig/twig/test/Twig/Tests/ErrorTest.php +8 -8
- library/twig/twig/test/Twig/Tests/ExpressionParserTest.php +17 -17
- library/twig/twig/test/Twig/Tests/Extension/CoreTest.php +1 -1
- library/twig/twig/test/Twig/Tests/Extension/SandboxTest.php +65 -0
- library/twig/twig/test/Twig/Tests/Fixtures/autoescape/block.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/autoescape/name.test +18 -0
- library/twig/twig/test/Twig/Tests/Fixtures/exceptions/child_contents_outside_blocks.test +15 -0
- library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/expressions/magic_call.test +11 -11
- library/twig/twig/test/Twig/Tests/Fixtures/expressions/power.test +20 -0
- library/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/filters/number_format_default.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/filters/static_calls.test +10 -0
- library/twig/twig/test/Twig/Tests/Fixtures/functions/block_with_template.test +22 -0
- library/twig/twig/test/Twig/Tests/Fixtures/functions/block_without_name.test +12 -0
- library/twig/twig/test/Twig/Tests/Fixtures/functions/date.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call.test +8 -0
- library/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call53.test +12 -0
- library/twig/twig/test/Twig/Tests/Fixtures/functions/static_calls.test +10 -0
- library/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test +0 -1
- library/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test +1 -1
- library/twig/twig/test/Twig/Tests/Fixtures/tags/with/basic.test +13 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tags/with/expression.test +10 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tags/with/nested.test +15 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_no_hash.test +10 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_only.test +10 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_attribute.test +35 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks.test +38 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test +17 -0
- library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_constants.test +14 -0
- library/twig/twig/test/Twig/Tests/IntegrationTest.php +27 -2
- library/twig/twig/test/Twig/Tests/LegacyFixtures/autoescape/filename.legacy.test +18 -0
- library/twig/twig/test/Twig/Tests/LexerTest.php +33 -22
- library/twig/twig/test/Twig/Tests/Loader/ArrayTest.php +16 -2
- library/twig/twig/test/Twig/Tests/Loader/ChainTest.php +46 -5
- library/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php +55 -11
- library/twig/twig/test/Twig/Tests/Loader/Fixtures/phar/phar-sample.phar +0 -0
- library/twig/twig/test/Twig/Tests/NativeExtensionTest.php +3 -0
- library/twig/twig/test/Twig/Tests/Node/Expression/NameTest.php +9 -1
- library/twig/twig/test/Twig/Tests/Node/Expression/NullCoalesceTest.php +31 -0
- library/twig/twig/test/Twig/Tests/Node/ModuleTest.php +35 -10
- library/twig/twig/test/Twig/Tests/Node/SandboxTest.php +1 -1
- library/twig/twig/test/Twig/Tests/Node/SandboxedPrintTest.php +1 -1
- library/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php +4 -4
- library/twig/twig/test/Twig/Tests/ParserTest.php +4 -3
- library/twig/twig/test/Twig/Tests/TemplateTest.php +111 -26
- library/twig/twig/test/Twig/Tests/TemplateWrapperTest.php +64 -0
- library/twig/twig/test/Twig/Tests/TokenStreamTest.php +12 -0
- library/twig/twig/test/Twig/Tests/escapingTest.php +1 -1
- readme.txt +31 -7
- wpcf.php +4 -3
application/controllers/field/utils.php
CHANGED
@@ -74,6 +74,28 @@ final class Types_Field_Utils {
|
|
74 |
}
|
75 |
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
private static $domain_legacy_value_map = array(
|
78 |
self::DOMAIN_POSTS => 'postmeta',
|
79 |
self::DOMAIN_USERS => 'usermeta',
|
@@ -128,7 +150,9 @@ final class Types_Field_Utils {
|
|
128 |
* Obtain toolset-forms "field configuration", which is an array of settings for specific field instance.
|
129 |
*
|
130 |
* @param WPCF_Field_Instance $field
|
|
|
131 |
* @since 1.9
|
|
|
132 |
*/
|
133 |
public static function get_toolset_forms_field_config( $field ) {
|
134 |
return wptoolset_form_filter_types_field(
|
74 |
}
|
75 |
|
76 |
|
77 |
+
/**
|
78 |
+
* Get the correct field group factory for provided underlying post type of the field group.
|
79 |
+
*
|
80 |
+
* This should not be needed from outside the legacy code.
|
81 |
+
*
|
82 |
+
* @param string $group_post_type
|
83 |
+
* @return Types_Field_Group_Factory
|
84 |
+
* @throws InvalidArgumentException when the post type doesn't belong to any field group.
|
85 |
+
* @since 2.2.4
|
86 |
+
*/
|
87 |
+
public static function get_group_factory_by_post_type( $group_post_type ) {
|
88 |
+
$domains = self::get_domains();
|
89 |
+
foreach( $domains as $domain ) {
|
90 |
+
$factory = Types_Field_Group_Factory::get_factory_by_domain( $domain );
|
91 |
+
if( $factory->get_post_type() == $group_post_type ) {
|
92 |
+
return $factory;
|
93 |
+
}
|
94 |
+
}
|
95 |
+
throw new InvalidArgumentException( 'Invalid field group post type.' );
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
private static $domain_legacy_value_map = array(
|
100 |
self::DOMAIN_POSTS => 'postmeta',
|
101 |
self::DOMAIN_USERS => 'usermeta',
|
150 |
* Obtain toolset-forms "field configuration", which is an array of settings for specific field instance.
|
151 |
*
|
152 |
* @param WPCF_Field_Instance $field
|
153 |
+
*
|
154 |
* @since 1.9
|
155 |
+
* @return array
|
156 |
*/
|
157 |
public static function get_toolset_forms_field_config( $field ) {
|
158 |
return wptoolset_form_filter_types_field(
|
application/controllers/utils.php
CHANGED
@@ -34,18 +34,18 @@ final class Types_Utils {
|
|
34 |
// todo add simple caching
|
35 |
$taxonomies = array();
|
36 |
|
37 |
-
// Read
|
38 |
-
$
|
39 |
-
if ( is_array( $
|
40 |
-
foreach ( $
|
41 |
$taxonomies[ $slug ] = $data;
|
42 |
}
|
43 |
}
|
44 |
|
45 |
-
// Get
|
46 |
-
$
|
47 |
-
foreach ( $
|
48 |
-
// check if
|
49 |
if ( isset( $taxonomies[ $slug ] ) ) {
|
50 |
continue;
|
51 |
}
|
@@ -218,4 +218,4 @@ final class Types_Utils {
|
|
218 |
}
|
219 |
|
220 |
|
221 |
-
}
|
34 |
// todo add simple caching
|
35 |
$taxonomies = array();
|
36 |
|
37 |
+
// Read Types taxonomies first.
|
38 |
+
$types_taxonomies = get_option( WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array() );
|
39 |
+
if ( is_array( $types_taxonomies ) ) {
|
40 |
+
foreach ( $types_taxonomies as $slug => $data ) {
|
41 |
$taxonomies[ $slug ] = $data;
|
42 |
}
|
43 |
}
|
44 |
|
45 |
+
// Get all taxonomies and add them to the set, but avoid overwriting Types taxonomies
|
46 |
+
$all_taxonomies = self::object_to_array_deep( get_taxonomies( array( 'public' => true ) , 'objects' ) );
|
47 |
+
foreach ( $all_taxonomies as $slug => $data ) {
|
48 |
+
// check if taxonomies are already saved as custom taxonomies
|
49 |
if ( isset( $taxonomies[ $slug ] ) ) {
|
50 |
continue;
|
51 |
}
|
218 |
}
|
219 |
|
220 |
|
221 |
+
}
|
application/functions.php
CHANGED
@@ -68,7 +68,7 @@ if( !function_exists( 'wpcf_getarr' ) ) {
|
|
68 |
* @since 1.9
|
69 |
*/
|
70 |
function wpcf_getarr( &$source, $key, $default = '', $valid = null ) {
|
71 |
-
if (
|
72 |
$val = $source[ $key ];
|
73 |
if ( is_array( $valid ) && ! in_array( $val, $valid ) ) {
|
74 |
return $default;
|
68 |
* @since 1.9
|
69 |
*/
|
70 |
function wpcf_getarr( &$source, $key, $default = '', $valid = null ) {
|
71 |
+
if ( is_array( $source ) && array_key_exists( $key, $source ) ) {
|
72 |
$val = $source[ $key ];
|
73 |
if ( is_array( $valid ) && ! in_array( $val, $valid ) ) {
|
74 |
return $default;
|
application/models/wpml/field/group/string.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Types_Wpml_Field_Group_String implements Types_Wpml_Interface {
|
4 |
+
|
5 |
+
const CONTEXT = 'plugin Types';
|
6 |
+
const TRANSLATE_FILTER = 'wpml_translate_single_string';
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @var Types_Field_Group
|
10 |
+
*/
|
11 |
+
protected $group;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* String to translate
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
protected $string_to_translate;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Types_Wpml_Field_Group_String constructor.
|
21 |
+
*
|
22 |
+
* @param Types_Field_Group $group
|
23 |
+
*/
|
24 |
+
public function __construct( Types_Field_Group $group ) {
|
25 |
+
$this->group = $group;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* The pattern of the string name in icl_strings
|
30 |
+
* - [name]: group %s name
|
31 |
+
* - [description]: group %s description
|
32 |
+
*
|
33 |
+
* @return string
|
34 |
+
*/
|
35 |
+
abstract protected function get_db_pattern();
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Returns the string which should be translated
|
40 |
+
*
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
protected function get_string_to_translate() {
|
44 |
+
return $this->string_to_translate;
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get the db identifier (uses slug of group)
|
50 |
+
*
|
51 |
+
* @return string
|
52 |
+
*/
|
53 |
+
protected function get_db_identifier() {
|
54 |
+
return sprintf( $this->get_db_pattern(), $this->group->get_slug() );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get the db identifier (uses id of group)
|
59 |
+
*
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
protected function get_db_identifier_legacy() {
|
63 |
+
return sprintf( $this->get_db_pattern(), $this->group->get_id() );
|
64 |
+
}
|
65 |
+
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Translate name of the group
|
69 |
+
*
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public function translate() {
|
73 |
+
if ( empty( $this->string_to_translate ) || ! is_string( $this->string_to_translate ) ) {
|
74 |
+
return $this->string_to_translate;
|
75 |
+
}
|
76 |
+
|
77 |
+
// trying the new pattern, which uses the GROUP NAME
|
78 |
+
$translated_string = $this->get_translation(
|
79 |
+
$this->string_to_translate,
|
80 |
+
$this->get_db_identifier()
|
81 |
+
);
|
82 |
+
|
83 |
+
if( $translated_string && $translated_string != $this->string_to_translate )
|
84 |
+
return $translated_string;
|
85 |
+
|
86 |
+
// nothing found yet, try the old pattern for group storage
|
87 |
+
return $this->translate_legacy();
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Returning the legacy pattern which is using the GROUP ID
|
92 |
+
*
|
93 |
+
* @return mixed|void
|
94 |
+
*/
|
95 |
+
private function translate_legacy() {
|
96 |
+
$translated_string = $this->get_translation(
|
97 |
+
$this->string_to_translate,
|
98 |
+
$this->get_db_identifier_legacy()
|
99 |
+
);
|
100 |
+
|
101 |
+
// no translation found
|
102 |
+
if( ! $translated_string )
|
103 |
+
return $this->string_to_translate;
|
104 |
+
|
105 |
+
// update pattern of name field in "icl_strings" table
|
106 |
+
// to use name of group instead of id
|
107 |
+
$this->update_db_identifier();
|
108 |
+
|
109 |
+
// return translated string
|
110 |
+
return $translated_string;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get translation of string
|
115 |
+
*
|
116 |
+
* @param $string
|
117 |
+
* @param $field_id
|
118 |
+
*
|
119 |
+
* @return string|false
|
120 |
+
*/
|
121 |
+
private function get_translation( $string, $field_id ) {
|
122 |
+
|
123 |
+
// check if translation exists
|
124 |
+
$is_registered = apply_filters(
|
125 |
+
'wpml_string_id',
|
126 |
+
null,
|
127 |
+
array(
|
128 |
+
'context' => self::CONTEXT,
|
129 |
+
'name' => $field_id
|
130 |
+
)
|
131 |
+
);
|
132 |
+
|
133 |
+
if( $is_registered === null )
|
134 |
+
return false;
|
135 |
+
|
136 |
+
// string is registered, return translation
|
137 |
+
return apply_filters(
|
138 |
+
self::TRANSLATE_FILTER,
|
139 |
+
$string,
|
140 |
+
self::CONTEXT,
|
141 |
+
$field_id
|
142 |
+
);
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Update the identifier on db table "{prefix}_icl_strings" to use the "name" of a group instead of the "id"
|
147 |
+
*/
|
148 |
+
private function update_db_identifier() {
|
149 |
+
global $wpdb;
|
150 |
+
|
151 |
+
$wpdb->query(
|
152 |
+
$wpdb->prepare(
|
153 |
+
"UPDATE {$wpdb->prefix}icl_strings
|
154 |
+
SET name = %s,
|
155 |
+
domain_name_context_md5 = md5( CONCAT( context, name, gettext_context ) )
|
156 |
+
WHERE name = %s",
|
157 |
+
$this->get_db_identifier(),
|
158 |
+
$this->get_db_identifier_legacy()
|
159 |
+
)
|
160 |
+
);
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Say Hello to WPML
|
165 |
+
*/
|
166 |
+
public function register( $slug_update = false ) {
|
167 |
+
// abort if needed function not exists
|
168 |
+
if( ! function_exists( 'icl_register_string' ) )
|
169 |
+
return;
|
170 |
+
|
171 |
+
// update string identifier
|
172 |
+
if( $slug_update ) {
|
173 |
+
global $wpdb;
|
174 |
+
|
175 |
+
$wpdb->query(
|
176 |
+
$wpdb->prepare(
|
177 |
+
"UPDATE {$wpdb->prefix}icl_strings
|
178 |
+
SET name = %s
|
179 |
+
WHERE name = %s",
|
180 |
+
$this->get_db_identifier(),
|
181 |
+
sprintf( $this->get_db_pattern(), $slug_update )
|
182 |
+
)
|
183 |
+
);
|
184 |
+
}
|
185 |
+
|
186 |
+
// register/update string
|
187 |
+
icl_register_string(
|
188 |
+
self::CONTEXT,
|
189 |
+
$this->get_db_identifier(),
|
190 |
+
$this->get_string_to_translate()
|
191 |
+
);
|
192 |
+
}
|
193 |
+
}
|
application/models/wpml/field/group/string/description.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
class Types_Wpml_Field_Group_String_Description extends Types_Wpml_Field_Group_String {
|
5 |
+
const DB_NAME_PATTERN = 'group %s description';
|
6 |
+
|
7 |
+
public function __construct( Types_Field_Group $group ) {
|
8 |
+
parent::__construct( $group );
|
9 |
+
$this->string_to_translate = stripslashes( $this->group->get_description() );
|
10 |
+
}
|
11 |
+
|
12 |
+
protected function get_db_pattern() {
|
13 |
+
return self::DB_NAME_PATTERN;
|
14 |
+
}
|
15 |
+
}
|
application/models/wpml/field/group/string/name.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
class Types_Wpml_Field_Group_String_Name extends Types_Wpml_Field_Group_String {
|
5 |
+
|
6 |
+
const DB_NAME_PATTERN = 'group %s name';
|
7 |
+
|
8 |
+
public function __construct( Types_Field_Group $group ) {
|
9 |
+
parent::__construct( $group );
|
10 |
+
$this->string_to_translate = stripslashes( $this->group->get_name() );
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function get_db_pattern() {
|
14 |
+
return self::DB_NAME_PATTERN;
|
15 |
+
}
|
16 |
+
}
|
application/models/wpml/field_group.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class Types_Wpml_Field_Group
|
5 |
+
*
|
6 |
+
* @fixme this is missing documentation
|
7 |
+
*
|
8 |
+
* @since 2.3
|
9 |
+
*/
|
10 |
+
class Types_Wpml_Field_Group implements Types_Wpml_Interface {
|
11 |
+
|
12 |
+
const STRING_NAME = 'name';
|
13 |
+
const STRING_DESCRIPTION = 'description';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var Types_Field_Group
|
17 |
+
*/
|
18 |
+
private $group;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var Types_Wpml_Interface
|
22 |
+
*/
|
23 |
+
private $name;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var Types_Wpml_Interface
|
27 |
+
*/
|
28 |
+
private $description;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Types_Wpml_Field_Group constructor.
|
32 |
+
*
|
33 |
+
* @param Types_Field_Group $group
|
34 |
+
*/
|
35 |
+
public function __construct( Types_Field_Group $group ) {
|
36 |
+
$this->group = $group;
|
37 |
+
|
38 |
+
// todo get rid of these hard dependencies
|
39 |
+
$this->name = new Types_Wpml_Field_Group_String_Name( $this->group );
|
40 |
+
$this->description = new Types_Wpml_Field_Group_String_Description( $this->group );
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Translate name or description of group
|
46 |
+
*
|
47 |
+
* @param string $part
|
48 |
+
*
|
49 |
+
* @return string
|
50 |
+
*/
|
51 |
+
public function translate( $part = self::STRING_NAME ) {
|
52 |
+
switch( $part ) {
|
53 |
+
case self::STRING_NAME:
|
54 |
+
return $this->translate_name();
|
55 |
+
break;
|
56 |
+
case self::STRING_DESCRIPTION:
|
57 |
+
return $this->translate_description();
|
58 |
+
break;
|
59 |
+
default:
|
60 |
+
return '';
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Translate name of the group
|
66 |
+
*
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
public function translate_name() {
|
70 |
+
return $this->name->translate();
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Translate description of group
|
75 |
+
*
|
76 |
+
* @return string
|
77 |
+
*/
|
78 |
+
public function translate_description() {
|
79 |
+
return $this->description->translate();
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Registration of name and description strings
|
84 |
+
* @param bool|string $slug_update
|
85 |
+
*/
|
86 |
+
public function register( $slug_update = false ) {
|
87 |
+
$this->name->register( $slug_update );
|
88 |
+
$this->description->register( $slug_update );
|
89 |
+
}
|
90 |
+
}
|
application/models/wpml/interface.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
interface Types_Wpml_Interface {
|
4 |
+
public function translate();
|
5 |
+
public function register( $slug_update = false );
|
6 |
+
}
|
examples/author.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This example file is a part of the Types plugin online documentation found at: https://wp-types.com/documentation/customizing-sites-using-php/
|
4 |
+
* It is based on the original Twenty Sixteen theme's archive.php file.
|
5 |
+
* It features additional code to render custom user fields created with the Types plugin.
|
6 |
+
*
|
7 |
+
* Please note that the names of the custom fields are for example purposes only and will not work in your site as-is. You need to edit this example according to the documentation mentioned above.
|
8 |
+
*
|
9 |
+
* The template for displaying custom author archive pages
|
10 |
+
*
|
11 |
+
*
|
12 |
+
* @package WordPress
|
13 |
+
* @subpackage Twenty_Sixteen
|
14 |
+
* @since Twenty Sixteen 1.0
|
15 |
+
*/
|
16 |
+
|
17 |
+
get_header(); ?>
|
18 |
+
|
19 |
+
<div id="primary" class="content-area">
|
20 |
+
<main id="main" class="site-main" role="main">
|
21 |
+
|
22 |
+
<?php if ( have_posts() ) : ?>
|
23 |
+
|
24 |
+
<header class="page-header">
|
25 |
+
<!-- TYPES TIP: using get_the_author_meta function to output author name as the archive's title -->
|
26 |
+
<?php
|
27 |
+
echo '<h1 class="page-title">Author: ' . get_the_author_meta( 'first_name' ) . ' ' . get_the_author_meta( 'last_name' ) . '</h1>';
|
28 |
+
?>
|
29 |
+
|
30 |
+
<!-- TYPES TIP: using get_avatar function to output author's avatar image -->
|
31 |
+
<div class="user-avatar"><?php echo get_avatar( get_the_author_meta( 'user_email' ), '150' ); ?></div>
|
32 |
+
|
33 |
+
<!-- TYPES TIP: using Types function to custom user fields -->
|
34 |
+
<p><strong>Specialty topics:</strong> <?php echo types_render_usermeta( "specialty-topics" ); ?><br />
|
35 |
+
<strong>Staff role:</strong> <?php echo types_render_usermeta( "staff-role" ); ?></p>
|
36 |
+
|
37 |
+
<!-- TYPES TIP: using the the_author_meta function to output the description of the user -->
|
38 |
+
<p><b>About:</b> <?php the_author_meta( 'description' ); ?></p>
|
39 |
+
|
40 |
+
</header><!-- .page-header -->
|
41 |
+
|
42 |
+
<hr />
|
43 |
+
|
44 |
+
|
45 |
+
<!-- TYPES TIP: Creating a custom query for our author/user to display posts belonging to the "Post" and "Book" post types -->
|
46 |
+
<?php
|
47 |
+
// Add Custom Post Type to author archive
|
48 |
+
$args = array(
|
49 |
+
'post_type' => array('post', 'book') ,
|
50 |
+
'author' => get_queried_object_id(), // this will be the author ID on the author page
|
51 |
+
'showposts' => 10
|
52 |
+
);
|
53 |
+
$custom_posts = new WP_Query( $args );
|
54 |
+
|
55 |
+
// Start the Loop.
|
56 |
+
while ( $custom_posts->have_posts() ) : $custom_posts->the_post();
|
57 |
+
|
58 |
+
/*
|
59 |
+
* Include the Post-Format-specific template for the content.
|
60 |
+
* If you want to override this in a child theme, then include a file
|
61 |
+
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
|
62 |
+
*/
|
63 |
+
|
64 |
+
get_template_part( 'template-parts/content', get_post_type() );
|
65 |
+
|
66 |
+
// End the loop.
|
67 |
+
endwhile;
|
68 |
+
|
69 |
+
// Previous/next page navigation.
|
70 |
+
the_posts_pagination( array(
|
71 |
+
'prev_text' => __( 'Previous page', 'twentysixteen' ),
|
72 |
+
'next_text' => __( 'Next page', 'twentysixteen' ),
|
73 |
+
'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>',
|
74 |
+
) );
|
75 |
+
|
76 |
+
// If no content, include the "No posts found" template.
|
77 |
+
else :
|
78 |
+
|
79 |
+
|
80 |
+
endif;
|
81 |
+
?>
|
82 |
+
|
83 |
+
</main><!-- .site-main -->
|
84 |
+
</div><!-- .content-area -->
|
85 |
+
|
86 |
+
<?php get_sidebar(); ?>
|
87 |
+
<?php get_footer(); ?>
|
examples/content-book.php
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This example file is a part of the Types plugin online documentation found at: https://wp-types.com/documentation/customizing-sites-using-php/
|
4 |
+
* It is based on the original Twenty Sixteen theme's template part file for displaying single items.
|
5 |
+
* It features additional code to render custom fields created with the Types plugin and some parent post contents.
|
6 |
+
*
|
7 |
+
* Please note that the names of the custom fields are for example purposes only and will not work in your site as-is. You need to edit this example according to the documentation mentioned above.
|
8 |
+
*
|
9 |
+
* The template part for displaying Book post content
|
10 |
+
*
|
11 |
+
* @package WordPress
|
12 |
+
* @subpackage Twenty_Sixteen
|
13 |
+
* @since Twenty Sixteen 1.0
|
14 |
+
*/
|
15 |
+
?>
|
16 |
+
|
17 |
+
<!-- Standard Twenty Sixteen article header output -->
|
18 |
+
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
19 |
+
<header class="entry-header">
|
20 |
+
<?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
|
21 |
+
<span class="sticky-post"><?php _e( 'Featured', 'twentysixteen' ); ?></span>
|
22 |
+
<?php endif; ?>
|
23 |
+
|
24 |
+
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
|
25 |
+
</header><!-- .entry-header -->
|
26 |
+
|
27 |
+
<?php twentysixteen_excerpt(); ?>
|
28 |
+
|
29 |
+
|
30 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom image field "Book Cover" -->
|
31 |
+
<?php echo types_render_field( "book-cover", array( "size" => "thumbnail" ) ); ?>
|
32 |
+
|
33 |
+
<div class="entry-content">
|
34 |
+
<?php
|
35 |
+
/* translators: %s: Name of current post */
|
36 |
+
the_content( sprintf(
|
37 |
+
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
38 |
+
get_the_title()
|
39 |
+
) );
|
40 |
+
|
41 |
+
wp_link_pages( array(
|
42 |
+
'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentysixteen' ) . '</span>',
|
43 |
+
'after' => '</div>',
|
44 |
+
'link_before' => '<span>',
|
45 |
+
'link_after' => '</span>',
|
46 |
+
'pagelink' => '<span class="screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>%',
|
47 |
+
'separator' => '<span class="screen-reader-text">, </span>',
|
48 |
+
) );
|
49 |
+
?>
|
50 |
+
|
51 |
+
|
52 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Number of pages" -->
|
53 |
+
<p><strong>Number of pages:</strong> <?php echo types_render_field( "number-of-pages"); ?></p>
|
54 |
+
|
55 |
+
|
56 |
+
<!-- TYPES TIP: Custom code to load and display contents of the parent ("Writer") post -->
|
57 |
+
<?php
|
58 |
+
// Get the ID of the parent post, which belongs to the "Writer" post type
|
59 |
+
$writer_id = wpcf_pr_post_get_belongs( get_the_ID(), 'writer' );
|
60 |
+
|
61 |
+
// Get all the parent (writer) post data
|
62 |
+
$writer_post = get_post( $writer_id );
|
63 |
+
|
64 |
+
// Get the title of the parent (writer) post
|
65 |
+
$writer_name = $writer_post->post_title;
|
66 |
+
|
67 |
+
// Get the contents of the parent (writer) post
|
68 |
+
$writer_content = $writer_post->post_content;
|
69 |
+
?>
|
70 |
+
<!-- After loading the data of the parent post we display it using our custom HTML structure -->
|
71 |
+
<div class="writer">
|
72 |
+
<h5>Author: <?php echo $writer_name; ?></h5>
|
73 |
+
<div class="writer-description"><?php echo $writer_content; ?></div>
|
74 |
+
|
75 |
+
<!-- We can use the "post_id" argument with the types_render_field function to get a custom field of any post -->
|
76 |
+
<div class="writer-photo"><?php echo types_render_field( 'author-image', array( 'post_id' => $writer_id, 'size' => 'thumbnail' ) );
|
77 |
+
?></div>
|
78 |
+
|
79 |
+
<br class="clear">
|
80 |
+
</div>
|
81 |
+
|
82 |
+
|
83 |
+
</div><!-- .entry-content -->
|
84 |
+
|
85 |
+
<!-- Standard Twenty Sixteen content footer output -->
|
86 |
+
<footer class="entry-footer">
|
87 |
+
<?php twentysixteen_entry_meta(); ?>
|
88 |
+
<?php
|
89 |
+
edit_post_link(
|
90 |
+
sprintf(
|
91 |
+
/* translators: %s: Name of current post */
|
92 |
+
__( 'Edit<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
93 |
+
get_the_title()
|
94 |
+
),
|
95 |
+
'<span class="edit-link">',
|
96 |
+
'</span>'
|
97 |
+
);
|
98 |
+
?>
|
99 |
+
</footer><!-- .entry-footer -->
|
100 |
+
</article><!-- #post-## -->
|
101 |
+
|
examples/content-consultant.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This example file is a part of the Types plugin online documentation found at: https://wp-types.com/documentation/customizing-sites-using-php/
|
4 |
+
* It is based on the original Twenty Sixteen theme's template part file for displaying single items.
|
5 |
+
* It features additional code to render custom fields created with the Types plugin.
|
6 |
+
*
|
7 |
+
* Please note that the names of the custom fields are for example purposes only and will not work in your site as-is. You need to edit this example according to the documentation mentioned above.
|
8 |
+
*
|
9 |
+
* The template part for displaying Consultant post content
|
10 |
+
*
|
11 |
+
* @package WordPress
|
12 |
+
* @subpackage Twenty_Sixteen
|
13 |
+
* @since Twenty Sixteen 1.0
|
14 |
+
*/
|
15 |
+
?>
|
16 |
+
|
17 |
+
<!-- Standard Twenty Sixteen article header output -->
|
18 |
+
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
19 |
+
<header class="entry-header">
|
20 |
+
<?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
|
21 |
+
<span class="sticky-post"><?php _e( 'Featured', 'twentysixteen' ); ?></span>
|
22 |
+
<?php endif; ?>
|
23 |
+
|
24 |
+
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
|
25 |
+
</header><!-- .entry-header -->
|
26 |
+
|
27 |
+
<?php twentysixteen_excerpt(); ?>
|
28 |
+
|
29 |
+
|
30 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Consultant Photo" -->
|
31 |
+
<?php echo types_render_field( "consultant-photo", array( "size" => "thumbnail" )); ?>
|
32 |
+
|
33 |
+
|
34 |
+
<div class="entry-content">
|
35 |
+
|
36 |
+
<!-- TYPES TIP: Custom call to get_the_term_list function to display a list of taxonomy terms that the current "Consultant" post belongs to -->
|
37 |
+
<?php echo get_the_term_list( $post->ID, 'spoken-language', '<p><strong>Spoken languages: </strong>', ', ', '</p>'); ?>
|
38 |
+
|
39 |
+
|
40 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Consultant Roles" -->
|
41 |
+
<p><strong>Role: <?php echo types_render_field( "consultant-roles" ); // Call to Types function for rendering a custom field "Consultant Roles" ?></strong></p>
|
42 |
+
|
43 |
+
|
44 |
+
<!-- Standard Twenty Sixteen content output -->
|
45 |
+
<?php
|
46 |
+
/* translators: %s: Name of current post */
|
47 |
+
the_content( sprintf(
|
48 |
+
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
49 |
+
get_the_title()
|
50 |
+
) );
|
51 |
+
|
52 |
+
wp_link_pages( array(
|
53 |
+
'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentysixteen' ) . '</span>',
|
54 |
+
'after' => '</div>',
|
55 |
+
'link_before' => '<span>',
|
56 |
+
'link_after' => '</span>',
|
57 |
+
'pagelink' => '<span class="screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>%',
|
58 |
+
'separator' => '<span class="screen-reader-text">, </span>',
|
59 |
+
) );
|
60 |
+
?>
|
61 |
+
|
62 |
+
|
63 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Consultant Contact Phone" -->
|
64 |
+
<p><strong>Contact Phone: <?php echo types_render_field( "consultant-phone-number"); ?></strong></p>
|
65 |
+
</div><!-- .entry-content -->
|
66 |
+
|
67 |
+
|
68 |
+
<!-- Standard Twenty Sixteen content footer output -->
|
69 |
+
<footer class="entry-footer">
|
70 |
+
<?php twentysixteen_entry_meta(); ?>
|
71 |
+
<?php
|
72 |
+
edit_post_link(
|
73 |
+
sprintf(
|
74 |
+
/* translators: %s: Name of current post */
|
75 |
+
__( 'Edit<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
76 |
+
get_the_title()
|
77 |
+
),
|
78 |
+
'<span class="edit-link">',
|
79 |
+
'</span>'
|
80 |
+
);
|
81 |
+
?>
|
82 |
+
</footer><!-- .entry-footer -->
|
83 |
+
</article><!-- #post-## -->
|
examples/content-house.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This example file is a part of the Types plugin online documentation found at: https://wp-types.com/documentation/customizing-sites-using-php/
|
4 |
+
* It is based on the original Twenty Sixteen theme's template part file for displaying single items.
|
5 |
+
* It features additional code to render custom fields created with the Types plugin, including an image gallery created with images from the repeating image field.
|
6 |
+
*
|
7 |
+
* Please note that the names of the custom fields are for example purposes only and will not work in your site as-is. You need to edit this example according to the documentation mentioned above.
|
8 |
+
*
|
9 |
+
* The template part for displaying single House posts
|
10 |
+
*
|
11 |
+
* @package WordPress
|
12 |
+
* @subpackage Twenty_Sixteen
|
13 |
+
* @since Twenty Sixteen 1.0
|
14 |
+
*/
|
15 |
+
?>
|
16 |
+
|
17 |
+
<!-- Standard Twenty Sixteen article header output -->
|
18 |
+
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
19 |
+
<header class="entry-header">
|
20 |
+
<?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
|
21 |
+
<span class="sticky-post"><?php _e( 'Featured', 'twentysixteen' ); ?></span>
|
22 |
+
<?php endif; ?>
|
23 |
+
|
24 |
+
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
|
25 |
+
</header><!-- .entry-header -->
|
26 |
+
|
27 |
+
<?php twentysixteen_excerpt(); ?>
|
28 |
+
|
29 |
+
|
30 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom image field "House Photos". We used the "index" attribute to display only the first, representative photo of a house. -->
|
31 |
+
<?php echo types_render_field( "house-photos", array( "size"=>"thumbnail", "index" => "0" ) ); ?>
|
32 |
+
|
33 |
+
|
34 |
+
<div class="entry-content">
|
35 |
+
|
36 |
+
<!-- Standard Twenty Sixteen content output -->
|
37 |
+
<?php
|
38 |
+
/* translators: %s: Name of current post */
|
39 |
+
the_content( sprintf(
|
40 |
+
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
41 |
+
get_the_title()
|
42 |
+
) );
|
43 |
+
|
44 |
+
wp_link_pages( array(
|
45 |
+
'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentysixteen' ) . '</span>',
|
46 |
+
'after' => '</div>',
|
47 |
+
'link_before' => '<span>',
|
48 |
+
'link_after' => '</span>',
|
49 |
+
'pagelink' => '<span class="screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>%',
|
50 |
+
'separator' => '<span class="screen-reader-text">, </span>',
|
51 |
+
) );
|
52 |
+
?>
|
53 |
+
|
54 |
+
|
55 |
+
|
56 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Size" belonging to a "Houses" post type -->
|
57 |
+
<p><strong>Size:</strong> <?php echo types_render_field( "size" ); ?></p>
|
58 |
+
|
59 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Area" belonging to a "Houses" post type -->
|
60 |
+
<p><strong>Area:</strong> <?php echo types_render_field( "area" ); ?></p>
|
61 |
+
|
62 |
+
<!-- TYPES TIP: Custom code to load Types function and render a REPEATING custom field "House Photos" but with each output thumbnail image also linking to the full-size image file (for lightbox effect, for example). -->
|
63 |
+
<p><strong>Property Photos</strong></p>
|
64 |
+
|
65 |
+
<?php
|
66 |
+
// Do nothing if we don't have Types.
|
67 |
+
if( apply_filters( 'types_is_active', false ) ) {
|
68 |
+
|
69 |
+
$output = '';
|
70 |
+
|
71 |
+
// ID of the current post
|
72 |
+
$post_id = get_the_ID();
|
73 |
+
|
74 |
+
// Slug of a Types repeating image field, without the "wpcf-" prefix.
|
75 |
+
$field_slug = 'house-photos'; // TODO set the field slug you want to display
|
76 |
+
|
77 |
+
// Parameters that define the field
|
78 |
+
$field_definition = wpcf_fields_get_field_by_slug( $field_slug );
|
79 |
+
if( ! empty( $field_definition ) ) {
|
80 |
+
|
81 |
+
// Get the raw field data.
|
82 |
+
$images = get_post_meta( $post_id, "wpcf-{$field_slug}" );
|
83 |
+
|
84 |
+
foreach( $images as $image_index => $image ) {
|
85 |
+
|
86 |
+
// Parameters for the Types field rendering mechanism.
|
87 |
+
$image_parameters = array(
|
88 |
+
'proportional' => 'true',
|
89 |
+
'url' => 'true',
|
90 |
+
'field_value' => $image
|
91 |
+
);
|
92 |
+
|
93 |
+
// Get an image of specific (maximum) proportions.
|
94 |
+
// NOTE: Update image size to your needs
|
95 |
+
$thumbnail_parameters = array_merge( $image_parameters, array( 'width' => '200', 'height' => '200' ) );
|
96 |
+
$thumbnail_url = types_render_field_single( $field_definition, $thumbnail_parameters, null, '', $image_index );
|
97 |
+
|
98 |
+
// Get the image in full size.
|
99 |
+
$fullsize_parameters = array_merge( $image_parameters, array( 'size' => 'full' ) );
|
100 |
+
$fullsize_url = types_render_field_single( $field_definition, $fullsize_parameters, null, '', $image_index );
|
101 |
+
|
102 |
+
// Append the markup (a thumbnail linking to the full image) to existing content.
|
103 |
+
// NOTE: Customize the output to your needs
|
104 |
+
$output .= sprintf(
|
105 |
+
'<div class="img"><a href=" '. $fullsize_url .' "><img src=" '. $thumbnail_url .' "></a></div>'
|
106 |
+
);
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
echo $output;
|
111 |
+
}
|
112 |
+
?>
|
113 |
+
|
114 |
+
</div><!-- .entry-content -->
|
115 |
+
|
116 |
+
<!-- Continue the standard Twenty Sixteen content footer output -->
|
117 |
+
<footer class="entry-footer">
|
118 |
+
<?php twentysixteen_entry_meta(); ?>
|
119 |
+
<?php
|
120 |
+
edit_post_link(
|
121 |
+
sprintf(
|
122 |
+
/* translators: %s: Name of current post */
|
123 |
+
__( 'Edit<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
124 |
+
get_the_title()
|
125 |
+
),
|
126 |
+
'<span class="edit-link">',
|
127 |
+
'</span>'
|
128 |
+
);
|
129 |
+
?>
|
130 |
+
</footer><!-- .entry-footer -->
|
131 |
+
</article><!-- #post-## -->
|
examples/content-writer.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This example file is a part of the Types plugin online documentation found at: https://wp-types.com/documentation/customizing-sites-using-php/
|
4 |
+
* It is based on the original Twenty Sixteen theme's template part file for displaying single items.
|
5 |
+
* It features additional code to render custom fields created with the Types plugin and display contents of child posts.
|
6 |
+
*
|
7 |
+
* The template part for displaying Author (Writer) post content
|
8 |
+
*
|
9 |
+
* @package WordPress
|
10 |
+
* @subpackage Twenty_Sixteen
|
11 |
+
* @since Twenty Sixteen 1.0
|
12 |
+
*/
|
13 |
+
?>
|
14 |
+
|
15 |
+
<!-- Standard Twenty Sixteen article header output -->
|
16 |
+
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
17 |
+
<header class="entry-header">
|
18 |
+
<?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
|
19 |
+
<span class="sticky-post"><?php _e( 'Featured', 'twentysixteen' ); ?></span>
|
20 |
+
<?php endif; ?>
|
21 |
+
|
22 |
+
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
|
23 |
+
</header><!-- .entry-header -->
|
24 |
+
|
25 |
+
<?php twentysixteen_excerpt(); ?>
|
26 |
+
|
27 |
+
|
28 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Author Image" -->
|
29 |
+
<?php echo types_render_field( "author-image", array( "size" => "thumbnail" )); ?>
|
30 |
+
|
31 |
+
|
32 |
+
<div class="entry-content">
|
33 |
+
|
34 |
+
<!-- Standard Twenty Sixteen content output -->
|
35 |
+
<?php
|
36 |
+
/* translators: %s: Name of current post */
|
37 |
+
the_content( sprintf(
|
38 |
+
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
39 |
+
get_the_title()
|
40 |
+
) );
|
41 |
+
?>
|
42 |
+
|
43 |
+
|
44 |
+
<!-- TYPES TIP: Custom section to display a list of child posts ("Books"), belonging to the currently displayed parent post ("Author") -->
|
45 |
+
<h4>Books from this author</h4>
|
46 |
+
|
47 |
+
<?php
|
48 |
+
// Using the Types function to load the contents of child posts and then starting a custom loop to output them
|
49 |
+
$child_posts = types_child_posts("book"); // Load the contents of related posts in the array
|
50 |
+
foreach ($child_posts as $child_post) { // Loop through each of the child post in the array
|
51 |
+
?>
|
52 |
+
|
53 |
+
<div class="book-listing">
|
54 |
+
<h5><?php echo $child_post->post_title; // Display the post title of a current child post ?></h5>
|
55 |
+
<?php echo types_render_field( "book-cover", array( "id"=> "$child_post->ID", "size" => "thumbnail" )); // Display the image coming from a custom field of the current child post ?>
|
56 |
+
</div>
|
57 |
+
|
58 |
+
|
59 |
+
<!-- Continuation of the standard Twenty Sixteen content output -->
|
60 |
+
<?php }
|
61 |
+
wp_link_pages( array(
|
62 |
+
'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentysixteen' ) . '</span>',
|
63 |
+
'after' => '</div>',
|
64 |
+
'link_before' => '<span>',
|
65 |
+
'link_after' => '</span>',
|
66 |
+
'pagelink' => '<span class="screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>%',
|
67 |
+
'separator' => '<span class="screen-reader-text">, </span>',
|
68 |
+
) );
|
69 |
+
?>
|
70 |
+
|
71 |
+
</div><!-- .entry-content -->
|
72 |
+
|
73 |
+
<footer class="entry-footer">
|
74 |
+
<?php twentysixteen_entry_meta(); ?>
|
75 |
+
<?php
|
76 |
+
edit_post_link(
|
77 |
+
sprintf(
|
78 |
+
/* translators: %s: Name of current post */
|
79 |
+
__( 'Edit<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
80 |
+
get_the_title()
|
81 |
+
),
|
82 |
+
'<span class="edit-link">',
|
83 |
+
'</span>'
|
84 |
+
);
|
85 |
+
?>
|
86 |
+
</footer><!-- .entry-footer -->
|
87 |
+
</article><!-- #post-## -->
|
88 |
+
|
examples/single-consultant.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This example file is a part of the Types plugin online documentation found at: https://wp-types.com/documentation/customizing-sites-using-php/
|
4 |
+
* It is based on the original Twenty Sixteen theme's single.php file.
|
5 |
+
* It does not use template parts, but loads the post contents directly.
|
6 |
+
* It also features additional code to render custom fields created with the Types plugin.
|
7 |
+
*
|
8 |
+
* Please note that the names of the custom fields are for example purposes only and will not work in your site as-is. You need to edit this example according to the documentation mentioned above.
|
9 |
+
*
|
10 |
+
* The template for displaying single "Consultant" posts
|
11 |
+
*
|
12 |
+
* @package WordPress
|
13 |
+
* @subpackage Twenty_Sixteen
|
14 |
+
* @since Twenty Sixteen 1.0
|
15 |
+
*/
|
16 |
+
|
17 |
+
get_header(); ?>
|
18 |
+
|
19 |
+
<div id="primary" class="content-area">
|
20 |
+
<main id="main" class="site-main" role="main">
|
21 |
+
<?php
|
22 |
+
// Start the loop.
|
23 |
+
while ( have_posts() ) : the_post();
|
24 |
+
?>
|
25 |
+
|
26 |
+
<!-- Standard Twenty Sixteen article header output -->
|
27 |
+
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
28 |
+
<header class="entry-header">
|
29 |
+
<?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
|
30 |
+
<span class="sticky-post"><?php _e( 'Featured', 'twentysixteen' ); ?></span>
|
31 |
+
<?php endif; ?>
|
32 |
+
|
33 |
+
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
|
34 |
+
</header><!-- .entry-header -->
|
35 |
+
|
36 |
+
<?php twentysixteen_excerpt(); ?>
|
37 |
+
|
38 |
+
|
39 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Consultant Photo" -->
|
40 |
+
<?php echo types_render_field( "consultant-photo", array( "size" => "thumbnail" )); ?>
|
41 |
+
|
42 |
+
|
43 |
+
<div class="entry-content">
|
44 |
+
|
45 |
+
|
46 |
+
<!-- TYPES TIP: Custom call to get_the_term_list function to display a list of taxonomy terms that the current "Consultant" post belongs to -->
|
47 |
+
<?php echo get_the_term_list( $post->ID, 'spoken-language', '<p><strong>Spoken languages: </strong>', ', ', '</p>'); ?>
|
48 |
+
|
49 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Consultant Roles" -->
|
50 |
+
<p><strong>Role: <?php echo types_render_field( "consultant-roles" ); // Call to Types function for rendering a custom field "Consultant Roles" ?></strong></p>
|
51 |
+
|
52 |
+
|
53 |
+
<!-- Standard Twenty Sixteen content output -->
|
54 |
+
<?php
|
55 |
+
/* translators: %s: Name of current post */
|
56 |
+
the_content( sprintf(
|
57 |
+
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
58 |
+
get_the_title()
|
59 |
+
) );
|
60 |
+
|
61 |
+
wp_link_pages( array(
|
62 |
+
'before' => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentysixteen' ) . '</span>',
|
63 |
+
'after' => '</div>',
|
64 |
+
'link_before' => '<span>',
|
65 |
+
'link_after' => '</span>',
|
66 |
+
'pagelink' => '<span class="screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>%',
|
67 |
+
'separator' => '<span class="screen-reader-text">, </span>',
|
68 |
+
) );
|
69 |
+
?>
|
70 |
+
|
71 |
+
<!-- TYPES TIP: Custom call to Types function to render a custom field "Consultant Contact Phone" -->
|
72 |
+
<p><strong>Contact Phone: <?php echo types_render_field( "consultant-phone-number"); ?></strong></p>
|
73 |
+
</div><!-- .entry-content -->
|
74 |
+
|
75 |
+
<!-- Standard Twenty Sixteen content footer output -->
|
76 |
+
<footer class="entry-footer">
|
77 |
+
<?php twentysixteen_entry_meta(); ?>
|
78 |
+
<?php
|
79 |
+
edit_post_link(
|
80 |
+
sprintf(
|
81 |
+
/* translators: %s: Name of current post */
|
82 |
+
__( 'Edit<span class="screen-reader-text"> "%s"</span>', 'twentysixteen' ),
|
83 |
+
get_the_title()
|
84 |
+
),
|
85 |
+
'<span class="edit-link">',
|
86 |
+
'</span>'
|
87 |
+
);
|
88 |
+
?>
|
89 |
+
</footer><!-- .entry-footer -->
|
90 |
+
</article><!-- #post-## -->
|
91 |
+
|
92 |
+
|
93 |
+
<?php
|
94 |
+
// TYPES TIP: all of the lines below this point are the standard part of a single.php of the Twenty Sixteen theme.
|
95 |
+
|
96 |
+
// If comments are open or we have at least one comment, load up the comment template.
|
97 |
+
if ( comments_open() || get_comments_number() ) {
|
98 |
+
comments_template();
|
99 |
+
}
|
100 |
+
|
101 |
+
if ( is_singular( 'attachment' ) ) {
|
102 |
+
// Parent post navigation.
|
103 |
+
the_post_navigation( array(
|
104 |
+
'prev_text' => _x( '<span class="meta-nav">Published in</span><span class="post-title">%title</span>', 'Parent post link', 'twentysixteen' ),
|
105 |
+
) );
|
106 |
+
} elseif ( is_singular( 'post' ) ) {
|
107 |
+
// Previous/next post navigation.
|
108 |
+
the_post_navigation( array(
|
109 |
+
'next_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Next', 'twentysixteen' ) . '</span> ' .
|
110 |
+
'<span class="screen-reader-text">' . __( 'Next post:', 'twentysixteen' ) . '</span> ' .
|
111 |
+
'<span class="post-title">%title</span>',
|
112 |
+
'prev_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Previous', 'twentysixteen' ) . '</span> ' .
|
113 |
+
'<span class="screen-reader-text">' . __( 'Previous post:', 'twentysixteen' ) . '</span> ' .
|
114 |
+
'<span class="post-title">%title</span>',
|
115 |
+
) );
|
116 |
+
}
|
117 |
+
|
118 |
+
// End of the loop.
|
119 |
+
endwhile;
|
120 |
+
?>
|
121 |
+
|
122 |
+
</main><!-- .site-main -->
|
123 |
+
|
124 |
+
<?php get_sidebar( 'content-bottom' ); ?>
|
125 |
+
|
126 |
+
</div><!-- .content-area -->
|
127 |
+
|
128 |
+
<?php get_sidebar(); ?>
|
129 |
+
<?php get_footer(); ?>
|
library/otgs/installer/changelog.txt
CHANGED
@@ -1,142 +1,150 @@
|
|
1 |
-
= 1.7.
|
2 |
-
*
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
*
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
*
|
24 |
-
|
25 |
-
= 1.7.
|
26 |
-
*
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
*
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
*
|
55 |
-
*
|
56 |
-
|
57 |
-
|
58 |
-
*
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
*
|
63 |
-
*
|
64 |
-
|
65 |
-
|
66 |
-
*
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
*
|
71 |
-
*
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
*
|
80 |
-
*
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
* Fixed bug
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
*
|
94 |
-
*
|
95 |
-
|
96 |
-
|
97 |
-
*
|
98 |
-
|
99 |
-
= 1.5.
|
100 |
-
*
|
101 |
-
*
|
102 |
-
|
103 |
-
|
104 |
-
*
|
105 |
-
*
|
106 |
-
|
107 |
-
|
108 |
-
*
|
109 |
-
*
|
110 |
-
|
111 |
-
= 1.
|
112 |
-
*
|
113 |
-
* Bug fix:
|
114 |
-
*
|
115 |
-
*
|
116 |
-
*
|
117 |
-
*
|
118 |
-
|
119 |
-
|
120 |
-
*
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
*
|
125 |
-
|
126 |
-
|
127 |
-
*
|
128 |
-
*
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
*
|
133 |
-
|
134 |
-
|
135 |
-
*
|
136 |
-
|
137 |
-
|
138 |
-
*
|
139 |
-
*
|
140 |
-
*
|
141 |
-
*
|
142 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
= 1.7.13 =
|
2 |
+
* Added sanitization for some inputs
|
3 |
+
* Fixed PHP notice being logged when installing a plugin from the WP plugins directory
|
4 |
+
|
5 |
+
= 1.7.12 =
|
6 |
+
* Allow to set the site keys in PHP (as constants)
|
7 |
+
* Fixed an issue with unregistered sites gets wrong info (or error) when clicking "View version x.y.x details" link
|
8 |
+
|
9 |
+
= 1.7.11 =
|
10 |
+
* Fixed styling for 'must-register' warnings on the plugins page
|
11 |
+
|
12 |
+
= 1.7.10 =
|
13 |
+
* Fixed a notice that was appearing when the site key registration failed
|
14 |
+
|
15 |
+
= 1.7.9 =
|
16 |
+
* Save the client_id value from the site_key_validation API call response and make it available via WP_Installer_API::get_ts_client_id API call
|
17 |
+
|
18 |
+
= 1.7.8 =
|
19 |
+
* Small fix for hiding the WPML registration notice
|
20 |
+
|
21 |
+
= 1.7.7 =
|
22 |
+
* Fixed js error showing up during registration
|
23 |
+
* Styles update for unified WPML messages
|
24 |
+
|
25 |
+
= 1.7.6 =
|
26 |
+
* Updated error messages when validating site keys and stopped removing site keys in case of communication errors
|
27 |
+
* Added a note for users who renewed or purchased new subscriptions and who need to revalidate their subscription from their websites
|
28 |
+
* Fixed a problem with the registrations for multi-site setups when WordPress was installed in a separate folder
|
29 |
+
|
30 |
+
= 1.7.5 =
|
31 |
+
* Fixed a bug causing registration to not be recognized for the entire network in the multi-site mode
|
32 |
+
|
33 |
+
= 1.7.4 =
|
34 |
+
* Use https for wp-types API
|
35 |
+
|
36 |
+
= 1.7.3 =
|
37 |
+
* Added a dependencies class and check for the windows paths length exception
|
38 |
+
* Bug fix: all downloads showed up twice on the plugins list whe upgrading from WPML 3.3
|
39 |
+
|
40 |
+
= 1.7.2 =
|
41 |
+
* Added an exception to handle the case when Types embedded is installer from Toolset Installer and its included Installer version overrides the one running the Toolset setup wizard
|
42 |
+
|
43 |
+
= 1.7.1 =
|
44 |
+
* Added an exception for the case of Types 1.8.9 (Installer 1.7.0) together with older WPML (older Installer)
|
45 |
+
|
46 |
+
= 1.7.0 =
|
47 |
+
* New format for the products data file.
|
48 |
+
* Other fixes
|
49 |
+
|
50 |
+
= 1.6.8 =
|
51 |
+
* Sanitized an input that was a potential security issue
|
52 |
+
|
53 |
+
= 1.6.7 =
|
54 |
+
* Fixed a bug causing repeated calls to the Toolset api to validate the user subscription
|
55 |
+
* Use https for API urls
|
56 |
+
|
57 |
+
= 1.6.6 =
|
58 |
+
* Fixed the 'Call to undefined function get_plugins()' issue
|
59 |
+
|
60 |
+
= 1.6.5 =
|
61 |
+
* Added configuration file for composer
|
62 |
+
* Updated how free plugins are shown on the plugins list (commercial tab)
|
63 |
+
* API calls for manipulating translation service preferences
|
64 |
+
* Support for hosting custom Installer packages on wpml.org
|
65 |
+
* Fixed a warning that was showing when using the OTGS_DISABLE_AUTO_UPDATES constant before any product data was downloaded
|
66 |
+
* Changed the frequency with which product updates are checked automatically (24 hours)
|
67 |
+
* Improved reporting for version numbers
|
68 |
+
|
69 |
+
= 1.6.4 =
|
70 |
+
* Enabled the OTGS_DISABLE_AUTO_UPDATES constant for theme update checks
|
71 |
+
* Fixed a bug that was causing Register links to show for all installed plugins
|
72 |
+
|
73 |
+
= 1.6.3 =
|
74 |
+
* Fixed performance issue related to themes upgrade logic
|
75 |
+
|
76 |
+
= 1.6 =
|
77 |
+
* Improved the way plugins are matched: not just by the folder name (slug) but also by name
|
78 |
+
* Added support for installing and upgrading themes from repositories (currently: Toolset themes)
|
79 |
+
* Added support for 'alias' plugins on the toolset and wpml repositories (currently: Types)
|
80 |
+
* Enhanced the progress animation during plugins downloading
|
81 |
+
|
82 |
+
= 1.5.6 =
|
83 |
+
* Updated the translations
|
84 |
+
* Fix for WPML 3.2 conditional upgrade logic
|
85 |
+
|
86 |
+
= 1.5.5 =
|
87 |
+
* Fixed the logic for the high_priority parameter
|
88 |
+
* Fixed js bug causing a conflict with NextGen
|
89 |
+
* Fixed bug preventing users to install and upgrade Types when they didn't have a Toolset subscription
|
90 |
+
* Fixed bug preventing users to upgrade from the embedded Types to the full version
|
91 |
+
|
92 |
+
= 1.5.4 =
|
93 |
+
* Option to disable auto-updates
|
94 |
+
* Escaped urls generated with add_query_arg
|
95 |
+
|
96 |
+
= 1.5.3 =
|
97 |
+
* Fixed bug in WP_Installer::custom_plugins_api_call (filter for plugins_api) causing conflicts with other filters for plugins_api
|
98 |
+
|
99 |
+
= 1.5.2 =
|
100 |
+
* More meaningful errors when plugin downloads fail
|
101 |
+
* WordPress 4.2 compatibility
|
102 |
+
* Performance improvements (will not load in places where it's not needed and not make unnecessary requests to the CDN)
|
103 |
+
* Support putting deps.xml config file in the theme folder (root)
|
104 |
+
* Included code for importing data for toolset plugins
|
105 |
+
* Use CloudFront urls for products list files
|
106 |
+
|
107 |
+
= 1.5.1 =
|
108 |
+
* Fix for allowing embedded plugins to be updated
|
109 |
+
* Logic for the migration from embedded plugins to full plugins
|
110 |
+
|
111 |
+
= 1.5 =
|
112 |
+
* Support for embedded plugins
|
113 |
+
* Bug fix: When user registers site key with trailing slash, downloads might not work
|
114 |
+
* Tweak: Set a higher timeout limit for the http requests to CDN and API
|
115 |
+
* API function: link to specific repository
|
116 |
+
* API function: get product price
|
117 |
+
* New method for defining affiliate info (with backwards compatibility)
|
118 |
+
|
119 |
+
= 1.4 =
|
120 |
+
* Show explicit error in case of connectivity issues while validating a key.
|
121 |
+
* Bug fix: Downloading plugins in bulk was broken by plugin that had a redirect after activation
|
122 |
+
* Display friendly error message when WordPress does not have permissions to write to the plugins folder
|
123 |
+
* Added support for configuration files to auto-download required plugins and theme keys
|
124 |
+
* Changed the "Update this info" button to "Check for updates" (it refreshes the subscription info and checks for updates)
|
125 |
+
* Support for high_priority parameter that allows setting priority for an Installer instance when more with the same version number exist.
|
126 |
+
* Config files from different instances are combined (define repositories in different instances)
|
127 |
+
* Updated support for conditional updates display for ICL users
|
128 |
+
* More friendly error reporting and handling when using an invalid site key or the plugins archives are not valid.
|
129 |
+
|
130 |
+
|
131 |
+
= 1.3.1 =
|
132 |
+
* Support for conditional release notification (ICanLocalize)
|
133 |
+
|
134 |
+
= 1.3 =
|
135 |
+
* Added a new repository: Toolset
|
136 |
+
* The product packages can be displayed hierarchically and ordered
|
137 |
+
* The link to automatically create site keys will follow through login on the account site (e.g. wpml.org, wp-types.com)
|
138 |
+
* Fixed animation issues (not showing in most browsers) when downloading plugins.
|
139 |
+
* Created an admin screen on the repository end (icl-mpp) to sho registration stats (site keys, site keys usage, components usage etc..).
|
140 |
+
* Bug fix: Renew and Upgrade buttons were not entirely clickable
|
141 |
+
* Bug fix: Action buttons (buy, renew, upgrade) were not displayed correctly when WPML was not active (Installer embedded in theme)
|
142 |
+
* Support for site-wide registration. Products can be registered on the network instead of on each site separately.
|
143 |
+
* Users are able to add either http or https version for any site urls. There will be one site key that will work with both http and https versions.
|
144 |
+
|
145 |
+
= 1.2 =
|
146 |
+
* Added pagination for site keys list of Account -> My Sites
|
147 |
+
* Reversed the order in which the site keys are displayed.
|
148 |
+
* Fixed problem with WPML registration information (site key) not being saved when the option_value field in the wp_options table used a different charset than the default WordPress charset defined in wp-config.php
|
149 |
+
* Allow registering new sites by clicking a link in the WordPress admin instead of copying and pasting the site url in the Account -> My Sites section
|
150 |
+
* Display more detailed debug information related to connectivity issues with the WPML repository
|
library/otgs/installer/includes/class-installer-dependencies.php
CHANGED
@@ -1,278 +1,278 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class Installer_Dependencies{
|
4 |
-
|
5 |
-
private $uploading_allowed = null;
|
6 |
-
private $is_win_paths_exception = array();
|
7 |
-
|
8 |
-
|
9 |
-
function __construct(){
|
10 |
-
|
11 |
-
add_action( 'admin_init', array( $this, 'prevent_plugins_update_on_plugins_page' ), 100);
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
global $pagenow;
|
16 |
-
if($pagenow == 'update.php'){
|
17 |
-
if(isset($_GET['action']) && $_GET['action'] == 'update-selected'){
|
18 |
-
add_action('admin_head', array($this, 'prevent_plugins_update_on_updates_screen')); //iframe/bulk
|
19 |
-
}else{
|
20 |
-
add_action('all_admin_notices', array($this, 'prevent_plugins_update_on_updates_screen')); //regular/singular
|
21 |
-
}
|
22 |
-
}
|
23 |
-
add_action('wp_ajax_update-plugin', array($this, 'prevent_plugins_update_on_updates_screen'), 0); // high priority, before WP
|
24 |
-
|
25 |
-
}
|
26 |
-
|
27 |
-
public function is_win_paths_exception($repository_id){
|
28 |
-
|
29 |
-
if(!isset($this->is_win_paths_exception[$repository_id])) {
|
30 |
-
|
31 |
-
$this->is_win_paths_exception[$repository_id] = false;
|
32 |
-
|
33 |
-
if ( strtoupper( substr( PHP_OS, 0, 3 ) ) === 'WIN' ) {
|
34 |
-
|
35 |
-
$windows_max_path_length = 256;
|
36 |
-
$longest_path['wpml'] = 109;
|
37 |
-
$longest_path['toolset'] = 99;
|
38 |
-
|
39 |
-
$margin = 15;
|
40 |
-
|
41 |
-
$upgrade_path_length = strlen( WP_CONTENT_DIR . '/upgrade' );
|
42 |
-
|
43 |
-
$installer_settings = WP_Installer()->settings;
|
44 |
-
|
45 |
-
if ( is_array( $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'] ) ) {
|
46 |
-
$a_plugin = current( $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'] );
|
47 |
-
$url = WP_Installer()->append_site_key_to_download_url( $a_plugin['url'], 'xxxxxx', $repository_id );
|
48 |
-
$tmpfname = wp_tempnam( $url );
|
49 |
-
|
50 |
-
$tmpname_length = strlen( basename( $tmpfname ) ) - 4; // -.tmp
|
51 |
-
|
52 |
-
if ( $upgrade_path_length + $tmpname_length + $longest_path[$repository_id] + $margin > $windows_max_path_length ) {
|
53 |
-
|
54 |
-
$this->is_win_paths_exception[$repository_id] = true;
|
55 |
-
|
56 |
-
}
|
57 |
-
|
58 |
-
}
|
59 |
-
|
60 |
-
|
61 |
-
}
|
62 |
-
|
63 |
-
}
|
64 |
-
|
65 |
-
return $this->is_win_paths_exception[$repository_id];
|
66 |
-
|
67 |
-
}
|
68 |
-
|
69 |
-
public function is_uploading_allowed(){
|
70 |
-
|
71 |
-
if(!isset($this->uploading_allowed)){
|
72 |
-
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
73 |
-
require_once WP_Installer()->plugin_path() . '/includes/installer-upgrader-skins.php';
|
74 |
-
|
75 |
-
$upgrader_skins = new Installer_Upgrader_Skins(); //use our custom (mute) Skin
|
76 |
-
$upgrader = new Plugin_Upgrader($upgrader_skins);
|
77 |
-
|
78 |
-
ob_start();
|
79 |
-
$res = $upgrader->fs_connect( array(WP_CONTENT_DIR, WP_PLUGIN_DIR) );
|
80 |
-
ob_end_clean();
|
81 |
-
|
82 |
-
if ( ! $res || is_wp_error( $res ) ) {
|
83 |
-
$this->uploading_allowed = false;
|
84 |
-
}else{
|
85 |
-
$this->uploading_allowed = true;
|
86 |
-
}
|
87 |
-
}
|
88 |
-
|
89 |
-
return $this->uploading_allowed;
|
90 |
-
|
91 |
-
}
|
92 |
-
|
93 |
-
public function cant_download($repository_id){
|
94 |
-
|
95 |
-
return !$this->is_uploading_allowed() || $this->is_win_paths_exception($repository_id);
|
96 |
-
|
97 |
-
}
|
98 |
-
|
99 |
-
public function win_paths_exception_message(){
|
100 |
-
return __('Downloading is not possible. WordPress cannot create required folders because of the
|
101 |
-
256 characters limitation of the current Windows environment.', 'installer');
|
102 |
-
}
|
103 |
-
|
104 |
-
public function prevent_plugins_update_on_plugins_page(){
|
105 |
-
|
106 |
-
$plugins = get_site_transient( 'update_plugins' );
|
107 |
-
if ( isset($plugins->response) && is_array($plugins->response) ) {
|
108 |
-
$plugins_with_updates = array_keys( $plugins->response );
|
109 |
-
}
|
110 |
-
|
111 |
-
if( !empty($plugins_with_updates) ) {
|
112 |
-
|
113 |
-
$plugins = get_plugins();
|
114 |
-
|
115 |
-
$installer_settings = WP_Installer()->settings;
|
116 |
-
foreach ($installer_settings['repositories'] as $repository_id => $repository) {
|
117 |
-
|
118 |
-
if ($this->is_win_paths_exception($repository_id)) {
|
119 |
-
|
120 |
-
$repositories_plugins = array();
|
121 |
-
foreach ($repository['data']['packages'] as $package) {
|
122 |
-
foreach ($package['products'] as $product) {
|
123 |
-
foreach ($product['plugins'] as $plugin_slug) {
|
124 |
-
$download = $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
125 |
-
if ( empty($download['free-on-wporg']) ) {
|
126 |
-
$repositories_plugins[$download['slug']] = $download['name'];
|
127 |
-
}
|
128 |
-
}
|
129 |
-
}
|
130 |
-
}
|
131 |
-
|
132 |
-
foreach ($plugins as $plugin_id => $plugin) {
|
133 |
-
|
134 |
-
if( in_array( $plugin_id, $plugins_with_updates ) ) {
|
135 |
-
|
136 |
-
$wp_plugin_slug = dirname($plugin_id);
|
137 |
-
if (empty($wp_plugin_slug)) {
|
138 |
-
$wp_plugin_slug = basename($plugin_id, '.php');
|
139 |
-
}
|
140 |
-
|
141 |
-
foreach ($repositories_plugins as $slug => $name) {
|
142 |
-
if ($wp_plugin_slug == $slug || $name == $plugin['Name'] || $name == $plugin['Title']) { //match order: slug, name, title
|
143 |
-
|
144 |
-
remove_action("after_plugin_row_$plugin_id", 'wp_plugin_update_row', 10, 2);
|
145 |
-
add_action("after_plugin_row_$plugin_id", array($this, 'wp_plugin_update_row_win_exception'), 10, 2);
|
146 |
-
|
147 |
-
}
|
148 |
-
}
|
149 |
-
|
150 |
-
}
|
151 |
-
|
152 |
-
}
|
153 |
-
|
154 |
-
}
|
155 |
-
|
156 |
-
|
157 |
-
}
|
158 |
-
|
159 |
-
}
|
160 |
-
|
161 |
-
}
|
162 |
-
|
163 |
-
public function wp_plugin_update_row_win_exception(){
|
164 |
-
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
|
165 |
-
echo '<tr class="plugin-update-tr">';
|
166 |
-
echo '<td class="plugin-update colspanchange" colspan="' . esc_attr( $wp_list_table->get_column_count() ) .
|
167 |
-
'"><div class="update-message">' . $this->win_paths_exception_message() . '</div></td>';
|
168 |
-
echo '</tr>';
|
169 |
-
}
|
170 |
-
|
171 |
-
public function prevent_plugins_update_on_updates_screen(){
|
172 |
-
|
173 |
-
if ( isset($_REQUEST['action']) ) {
|
174 |
-
|
175 |
-
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
|
176 |
-
|
177 |
-
$installer_settings = WP_Installer()->settings;
|
178 |
-
|
179 |
-
//bulk mode
|
180 |
-
if('update-selected' == $action) {
|
181 |
-
|
182 |
-
global $plugins;
|
183 |
-
|
184 |
-
if(isset($plugins) && is_array($plugins)) {
|
185 |
-
|
186 |
-
foreach ($plugins as $k => $plugin) {
|
187 |
-
|
188 |
-
$wp_plugin_slug = dirname($plugin);
|
189 |
-
|
190 |
-
foreach ($installer_settings['repositories'] as $repository_id => $repository) {
|
191 |
-
|
192 |
-
if( $this->is_win_paths_exception($repository_id) ){
|
193 |
-
|
194 |
-
foreach ($repository['data']['packages'] as $package) {
|
195 |
-
|
196 |
-
foreach ($package['products'] as $product) {
|
197 |
-
|
198 |
-
foreach ($product['plugins'] as $plugin_slug) {
|
199 |
-
|
200 |
-
$download = $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
201 |
-
|
202 |
-
if ($download['slug'] == $wp_plugin_slug && empty($download['free-on-wporg']) ) {
|
203 |
-
|
204 |
-
echo '<div class="updated error"><p>' . $this->win_paths_exception_message() .
|
205 |
-
' <strong>(' . $download['name'] . ')</strong>' . '</p></div>';
|
206 |
-
unset($plugins[$k]);
|
207 |
-
|
208 |
-
break(3);
|
209 |
-
|
210 |
-
}
|
211 |
-
|
212 |
-
}
|
213 |
-
|
214 |
-
}
|
215 |
-
|
216 |
-
}
|
217 |
-
|
218 |
-
|
219 |
-
}
|
220 |
-
|
221 |
-
}
|
222 |
-
|
223 |
-
}
|
224 |
-
|
225 |
-
}
|
226 |
-
|
227 |
-
}
|
228 |
-
|
229 |
-
|
230 |
-
if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
|
231 |
-
|
232 |
-
$plugin = isset($_REQUEST['plugin']) ? trim($_REQUEST['plugin']) : '';
|
233 |
-
|
234 |
-
$wp_plugin_slug = dirname($plugin);
|
235 |
-
|
236 |
-
foreach($installer_settings['repositories'] as $repository_id => $repository){
|
237 |
-
|
238 |
-
if( $this->is_win_paths_exception( $repository_id ) ) {
|
239 |
-
foreach ($repository['data']['packages'] as $package) {
|
240 |
-
|
241 |
-
foreach($package['products'] as $product) {
|
242 |
-
|
243 |
-
foreach($product['plugins'] as $plugin_slug) {
|
244 |
-
$download = $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
245 |
-
|
246 |
-
//match by folder, will change to match by name and folder
|
247 |
-
if ( $download['slug'] == $wp_plugin_slug && empty ($download['free-on-wporg'] ) ) {
|
248 |
-
|
249 |
-
echo '<div class="updated error"><p>' . $this->win_paths_exception_message() . '</p></div>';
|
250 |
-
|
251 |
-
echo '<div class="wrap">';
|
252 |
-
echo '<h2>' . __('Update Plugin') . '</h2>';
|
253 |
-
echo '<a href="' . admin_url('update-core.php') . '">' . __('Return to the updates page', 'installer') . '</a>';
|
254 |
-
echo '</div>';
|
255 |
-
require_once(ABSPATH . 'wp-admin/admin-footer.php');
|
256 |
-
exit;
|
257 |
-
|
258 |
-
}
|
259 |
-
|
260 |
-
}
|
261 |
-
|
262 |
-
}
|
263 |
-
|
264 |
-
}
|
265 |
-
}
|
266 |
-
|
267 |
-
}
|
268 |
-
|
269 |
-
}
|
270 |
-
}
|
271 |
-
|
272 |
-
}
|
273 |
-
|
274 |
-
|
275 |
-
}
|
276 |
-
|
277 |
-
|
278 |
-
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Installer_Dependencies{
|
4 |
+
|
5 |
+
private $uploading_allowed = null;
|
6 |
+
private $is_win_paths_exception = array();
|
7 |
+
|
8 |
+
|
9 |
+
function __construct(){
|
10 |
+
|
11 |
+
add_action( 'admin_init', array( $this, 'prevent_plugins_update_on_plugins_page' ), 100);
|
12 |
+
|
13 |
+
|
14 |
+
|
15 |
+
global $pagenow;
|
16 |
+
if($pagenow == 'update.php'){
|
17 |
+
if(isset($_GET['action']) && $_GET['action'] == 'update-selected'){
|
18 |
+
add_action('admin_head', array($this, 'prevent_plugins_update_on_updates_screen')); //iframe/bulk
|
19 |
+
}else{
|
20 |
+
add_action('all_admin_notices', array($this, 'prevent_plugins_update_on_updates_screen')); //regular/singular
|
21 |
+
}
|
22 |
+
}
|
23 |
+
add_action('wp_ajax_update-plugin', array($this, 'prevent_plugins_update_on_updates_screen'), 0); // high priority, before WP
|
24 |
+
|
25 |
+
}
|
26 |
+
|
27 |
+
public function is_win_paths_exception($repository_id){
|
28 |
+
|
29 |
+
if(!isset($this->is_win_paths_exception[$repository_id])) {
|
30 |
+
|
31 |
+
$this->is_win_paths_exception[$repository_id] = false;
|
32 |
+
|
33 |
+
if ( strtoupper( substr( PHP_OS, 0, 3 ) ) === 'WIN' ) {
|
34 |
+
|
35 |
+
$windows_max_path_length = 256;
|
36 |
+
$longest_path['wpml'] = 109;
|
37 |
+
$longest_path['toolset'] = 99;
|
38 |
+
|
39 |
+
$margin = 15;
|
40 |
+
|
41 |
+
$upgrade_path_length = strlen( WP_CONTENT_DIR . '/upgrade' );
|
42 |
+
|
43 |
+
$installer_settings = WP_Installer()->settings;
|
44 |
+
|
45 |
+
if ( is_array( $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'] ) ) {
|
46 |
+
$a_plugin = current( $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'] );
|
47 |
+
$url = WP_Installer()->append_site_key_to_download_url( $a_plugin['url'], 'xxxxxx', $repository_id );
|
48 |
+
$tmpfname = wp_tempnam( $url );
|
49 |
+
|
50 |
+
$tmpname_length = strlen( basename( $tmpfname ) ) - 4; // -.tmp
|
51 |
+
|
52 |
+
if ( $upgrade_path_length + $tmpname_length + $longest_path[$repository_id] + $margin > $windows_max_path_length ) {
|
53 |
+
|
54 |
+
$this->is_win_paths_exception[$repository_id] = true;
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
}
|
62 |
+
|
63 |
+
}
|
64 |
+
|
65 |
+
return $this->is_win_paths_exception[$repository_id];
|
66 |
+
|
67 |
+
}
|
68 |
+
|
69 |
+
public function is_uploading_allowed(){
|
70 |
+
|
71 |
+
if(!isset($this->uploading_allowed)){
|
72 |
+
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
73 |
+
require_once WP_Installer()->plugin_path() . '/includes/installer-upgrader-skins.php';
|
74 |
+
|
75 |
+
$upgrader_skins = new Installer_Upgrader_Skins(); //use our custom (mute) Skin
|
76 |
+
$upgrader = new Plugin_Upgrader($upgrader_skins);
|
77 |
+
|
78 |
+
ob_start();
|
79 |
+
$res = $upgrader->fs_connect( array(WP_CONTENT_DIR, WP_PLUGIN_DIR) );
|
80 |
+
ob_end_clean();
|
81 |
+
|
82 |
+
if ( ! $res || is_wp_error( $res ) ) {
|
83 |
+
$this->uploading_allowed = false;
|
84 |
+
}else{
|
85 |
+
$this->uploading_allowed = true;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
return $this->uploading_allowed;
|
90 |
+
|
91 |
+
}
|
92 |
+
|
93 |
+
public function cant_download($repository_id){
|
94 |
+
|
95 |
+
return !$this->is_uploading_allowed() || $this->is_win_paths_exception($repository_id);
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
public function win_paths_exception_message(){
|
100 |
+
return __('Downloading is not possible. WordPress cannot create required folders because of the
|
101 |
+
256 characters limitation of the current Windows environment.', 'installer');
|
102 |
+
}
|
103 |
+
|
104 |
+
public function prevent_plugins_update_on_plugins_page(){
|
105 |
+
|
106 |
+
$plugins = get_site_transient( 'update_plugins' );
|
107 |
+
if ( isset($plugins->response) && is_array($plugins->response) ) {
|
108 |
+
$plugins_with_updates = array_keys( $plugins->response );
|
109 |
+
}
|
110 |
+
|
111 |
+
if( !empty($plugins_with_updates) ) {
|
112 |
+
|
113 |
+
$plugins = get_plugins();
|
114 |
+
|
115 |
+
$installer_settings = WP_Installer()->settings;
|
116 |
+
foreach ($installer_settings['repositories'] as $repository_id => $repository) {
|
117 |
+
|
118 |
+
if ($this->is_win_paths_exception($repository_id)) {
|
119 |
+
|
120 |
+
$repositories_plugins = array();
|
121 |
+
foreach ($repository['data']['packages'] as $package) {
|
122 |
+
foreach ($package['products'] as $product) {
|
123 |
+
foreach ($product['plugins'] as $plugin_slug) {
|
124 |
+
$download = $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
125 |
+
if ( empty($download['free-on-wporg']) ) {
|
126 |
+
$repositories_plugins[$download['slug']] = $download['name'];
|
127 |
+
}
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
foreach ($plugins as $plugin_id => $plugin) {
|
133 |
+
|
134 |
+
if( in_array( $plugin_id, $plugins_with_updates ) ) {
|
135 |
+
|
136 |
+
$wp_plugin_slug = dirname($plugin_id);
|
137 |
+
if (empty($wp_plugin_slug)) {
|
138 |
+
$wp_plugin_slug = basename($plugin_id, '.php');
|
139 |
+
}
|
140 |
+
|
141 |
+
foreach ($repositories_plugins as $slug => $name) {
|
142 |
+
if ($wp_plugin_slug == $slug || $name == $plugin['Name'] || $name == $plugin['Title']) { //match order: slug, name, title
|
143 |
+
|
144 |
+
remove_action("after_plugin_row_$plugin_id", 'wp_plugin_update_row', 10, 2);
|
145 |
+
add_action("after_plugin_row_$plugin_id", array($this, 'wp_plugin_update_row_win_exception'), 10, 2);
|
146 |
+
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
}
|
151 |
+
|
152 |
+
}
|
153 |
+
|
154 |
+
}
|
155 |
+
|
156 |
+
|
157 |
+
}
|
158 |
+
|
159 |
+
}
|
160 |
+
|
161 |
+
}
|
162 |
+
|
163 |
+
public function wp_plugin_update_row_win_exception(){
|
164 |
+
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
|
165 |
+
echo '<tr class="plugin-update-tr">';
|
166 |
+
echo '<td class="plugin-update colspanchange" colspan="' . esc_attr( $wp_list_table->get_column_count() ) .
|
167 |
+
'"><div class="update-message">' . $this->win_paths_exception_message() . '</div></td>';
|
168 |
+
echo '</tr>';
|
169 |
+
}
|
170 |
+
|
171 |
+
public function prevent_plugins_update_on_updates_screen(){
|
172 |
+
|
173 |
+
if ( isset($_REQUEST['action']) ) {
|
174 |
+
|
175 |
+
$action = isset($_REQUEST['action']) ? sanitize_text_field ( $_REQUEST['action'] ) : '';
|
176 |
+
|
177 |
+
$installer_settings = WP_Installer()->settings;
|
178 |
+
|
179 |
+
//bulk mode
|
180 |
+
if('update-selected' == $action) {
|
181 |
+
|
182 |
+
global $plugins;
|
183 |
+
|
184 |
+
if(isset($plugins) && is_array($plugins)) {
|
185 |
+
|
186 |
+
foreach ($plugins as $k => $plugin) {
|
187 |
+
|
188 |
+
$wp_plugin_slug = dirname($plugin);
|
189 |
+
|
190 |
+
foreach ($installer_settings['repositories'] as $repository_id => $repository) {
|
191 |
+
|
192 |
+
if( $this->is_win_paths_exception($repository_id) ){
|
193 |
+
|
194 |
+
foreach ($repository['data']['packages'] as $package) {
|
195 |
+
|
196 |
+
foreach ($package['products'] as $product) {
|
197 |
+
|
198 |
+
foreach ($product['plugins'] as $plugin_slug) {
|
199 |
+
|
200 |
+
$download = $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
201 |
+
|
202 |
+
if ($download['slug'] == $wp_plugin_slug && empty($download['free-on-wporg']) ) {
|
203 |
+
|
204 |
+
echo '<div class="updated error"><p>' . $this->win_paths_exception_message() .
|
205 |
+
' <strong>(' . $download['name'] . ')</strong>' . '</p></div>';
|
206 |
+
unset($plugins[$k]);
|
207 |
+
|
208 |
+
break(3);
|
209 |
+
|
210 |
+
}
|
211 |
+
|
212 |
+
}
|
213 |
+
|
214 |
+
}
|
215 |
+
|
216 |
+
}
|
217 |
+
|
218 |
+
|
219 |
+
}
|
220 |
+
|
221 |
+
}
|
222 |
+
|
223 |
+
}
|
224 |
+
|
225 |
+
}
|
226 |
+
|
227 |
+
}
|
228 |
+
|
229 |
+
|
230 |
+
if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
|
231 |
+
|
232 |
+
$plugin = isset($_REQUEST['plugin']) ? trim( sanitize_text_field ( $_REQUEST['plugin'] ) ) : '';
|
233 |
+
|
234 |
+
$wp_plugin_slug = dirname($plugin);
|
235 |
+
|
236 |
+
foreach($installer_settings['repositories'] as $repository_id => $repository){
|
237 |
+
|
238 |
+
if( $this->is_win_paths_exception( $repository_id ) ) {
|
239 |
+
foreach ($repository['data']['packages'] as $package) {
|
240 |
+
|
241 |
+
foreach($package['products'] as $product) {
|
242 |
+
|
243 |
+
foreach($product['plugins'] as $plugin_slug) {
|
244 |
+
$download = $installer_settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
245 |
+
|
246 |
+
//match by folder, will change to match by name and folder
|
247 |
+
if ( $download['slug'] == $wp_plugin_slug && empty ($download['free-on-wporg'] ) ) {
|
248 |
+
|
249 |
+
echo '<div class="updated error"><p>' . $this->win_paths_exception_message() . '</p></div>';
|
250 |
+
|
251 |
+
echo '<div class="wrap">';
|
252 |
+
echo '<h2>' . __('Update Plugin') . '</h2>';
|
253 |
+
echo '<a href="' . admin_url('update-core.php') . '">' . __('Return to the updates page', 'installer') . '</a>';
|
254 |
+
echo '</div>';
|
255 |
+
require_once(ABSPATH . 'wp-admin/admin-footer.php');
|
256 |
+
exit;
|
257 |
+
|
258 |
+
}
|
259 |
+
|
260 |
+
}
|
261 |
+
|
262 |
+
}
|
263 |
+
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
}
|
268 |
+
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
}
|
273 |
+
|
274 |
+
|
275 |
+
}
|
276 |
+
|
277 |
+
|
278 |
+
|
library/otgs/installer/includes/class-installer-theme.php
CHANGED
@@ -1,979 +1,979 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Installer Class for Theme Support
|
4 |
-
*
|
5 |
-
* Supports automatic updates and installation of Toolset/WPML Themes
|
6 |
-
*
|
7 |
-
* @class Installer_Theme_Class
|
8 |
-
* @version 1.6
|
9 |
-
* @category Class
|
10 |
-
* @author OnTheGoSystems
|
11 |
-
*/
|
12 |
-
|
13 |
-
if ( !defined( 'ABSPATH' ) ) {
|
14 |
-
exit;
|
15 |
-
}
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Installer_Theme_Class
|
19 |
-
*/
|
20 |
-
class Installer_Theme_Class {
|
21 |
-
|
22 |
-
/** Theme Repository */
|
23 |
-
private $theme_repo;
|
24 |
-
|
25 |
-
/** Repository API */
|
26 |
-
private $repository_api;
|
27 |
-
|
28 |
-
/** Repository Theme Products */
|
29 |
-
private $repository_theme_products;
|
30 |
-
|
31 |
-
/** Site URL */
|
32 |
-
private $installer_site_url;
|
33 |
-
|
34 |
-
/** Site Key */
|
35 |
-
private $installer_site_key;
|
36 |
-
|
37 |
-
/** The Themes Option */
|
38 |
-
protected $installer_themes_option;
|
39 |
-
|
40 |
-
/** Update settings */
|
41 |
-
protected $installer_themes_available_updates;
|
42 |
-
|
43 |
-
/** The Themes */
|
44 |
-
protected $installer_themes = array();
|
45 |
-
|
46 |
-
/** Repository with themes */
|
47 |
-
protected $installer_repo_with_themes;
|
48 |
-
|
49 |
-
/** Active tab */
|
50 |
-
protected $installer_theme_active_tab;
|
51 |
-
|
52 |
-
/** Theme user registration */
|
53 |
-
protected $theme_user_registration;
|
54 |
-
|
55 |
-
/** Client active subscription */
|
56 |
-
protected $installer_theme_subscription_type;
|
57 |
-
|
58 |
-
public function __construct() {
|
59 |
-
|
60 |
-
/** Properties */
|
61 |
-
|
62 |
-
//Get installer repositories
|
63 |
-
$installer_repositories = WP_Installer()->get_repositories();
|
64 |
-
|
65 |
-
//Get repos with themes
|
66 |
-
$repos_with_themes = $this->installer_theme_reposities_that_has_themes( $installer_repositories );
|
67 |
-
|
68 |
-
if ( is_array( $repos_with_themes ) ) {
|
69 |
-
//Assign to property
|
70 |
-
$this->installer_repo_with_themes = $repos_with_themes;
|
71 |
-
|
72 |
-
//Let's looped through repos with themes
|
73 |
-
foreach ( $repos_with_themes as $k => $repo ) {
|
74 |
-
|
75 |
-
//$repo could be 'toolset' or 'wpml'
|
76 |
-
//Assign each repo with theme to property
|
77 |
-
$this->theme_repo[] = $repo;
|
78 |
-
|
79 |
-
if ( (isset($installer_repositories[$repo]['api-url'])) && (isset($installer_repositories[$repo]['products'])) ) {
|
80 |
-
|
81 |
-
//Define the rest of the properties based on the given repo
|
82 |
-
$this->repository_api[$repo] = $installer_repositories[$repo]['api-url'];
|
83 |
-
$this->repository_theme_products[$repo] = $installer_repositories[$repo]['products'];
|
84 |
-
$this->installer_site_url[$repo] = WP_Installer()->get_installer_site_url( $repo );
|
85 |
-
$this->installer_site_key[$repo] = WP_Installer()->get_site_key( $repo );
|
86 |
-
$this->theme_user_registration[$repo] = false;
|
87 |
-
|
88 |
-
if ( WP_Installer()->repository_has_valid_subscription( $repo ) ) {
|
89 |
-
|
90 |
-
$this->installer_theme_subscription_type = WP_Installer()->get_subscription_type_for_repository( $repo );
|
91 |
-
$this->installer_themes_option[$repo] = 'wp_installer_' . $repo . '_themes';
|
92 |
-
$this->installer_themes_available_updates[$repo] = 'wp_installer_' . $repo . '_updated_themes';
|
93 |
-
$this->installer_theme_active_tab = '';
|
94 |
-
|
95 |
-
//We only set themes available to this validated subscription
|
96 |
-
$this->installer_theme_available( $repo, $this->installer_theme_subscription_type );
|
97 |
-
|
98 |
-
add_action( 'installer_themes_support_set_up', array($this, 'installer_theme_sets_active_tab_on_init'), 10 );
|
99 |
-
$this->theme_user_registration[$repo] = true;
|
100 |
-
}
|
101 |
-
|
102 |
-
/** We are ready.. let's initialize .... */
|
103 |
-
$this->init();
|
104 |
-
}
|
105 |
-
}
|
106 |
-
add_action( 'installer_themes_support_set_up', array($this, 'installer_theme_loaded_hooks') );
|
107 |
-
}
|
108 |
-
}
|
109 |
-
|
110 |
-
/** Init */
|
111 |
-
public function init() {
|
112 |
-
add_action( 'admin_enqueue_scripts', array($this, 'installer_theme_enqueue_scripts') );
|
113 |
-
add_filter( 'themes_api', array($this, 'installer_theme_api_override'), 10, 3 );
|
114 |
-
add_filter( 'themes_api_result', array($this, 'installer_theme_api_override_response'), 10, 3 );
|
115 |
-
add_filter( 'site_transient_update_themes', array($this, 'installer_theme_upgrade_check'), 10, 1 );
|
116 |
-
add_action( 'http_api_debug', array($this, 'installer_theme_sync_native_wp_api'), 10, 5 );
|
117 |
-
add_filter( 'installer_theme_hook_response_theme', array($this, 'installer_theme_add_num_ratings'), 10, 1 );
|
118 |
-
add_filter( 'themes_update_check_locales', array($this, 'installer_theme_sync_call_wp_theme_api'), 10, 1 );
|
119 |
-
add_filter( 'admin_url', array($this, 'installer_theme_add_query_arg_tab'), 10, 3 );
|
120 |
-
add_filter( 'network_admin_url', array($this, 'installer_theme_add_query_arg_tab'), 10, 2 );
|
121 |
-
add_action( 'wp_ajax_installer_theme_frontend_selected_tab', array($this, 'installer_theme_frontend_selected_tab'), 0 );
|
122 |
-
add_action( 'wp_loaded', array($this, 'installer_themes_support_set_up_func') );
|
123 |
-
}
|
124 |
-
|
125 |
-
/** Enqueue scripts */
|
126 |
-
public function installer_theme_enqueue_scripts() {
|
127 |
-
$current_screen = $this->installer_theme_current_screen();
|
128 |
-
$commercial_plugin_screen = $this->installer_theme_is_commercial_plugin_screen( $current_screen );
|
129 |
-
if ( ('theme-install' == $current_screen) || ($commercial_plugin_screen) || ('theme-install-network' == $current_screen) ) {
|
130 |
-
$repo_with_themes = $this->installer_repo_with_themes;
|
131 |
-
$js_array = array();
|
132 |
-
if ( is_array( $repo_with_themes ) ) {
|
133 |
-
foreach ( $repo_with_themes as $k => $v ) {
|
134 |
-
|
135 |
-
//Hyperlink text
|
136 |
-
$theme_repo_name = $this->installer_theme_get_repo_product_name( $v );
|
137 |
-
$the_hyperlink_text = esc_js( $theme_repo_name );
|
138 |
-
|
139 |
-
if ( is_multisite() ) {
|
140 |
-
$admin_url_passed = network_admin_url();
|
141 |
-
} else {
|
142 |
-
$admin_url_passed = admin_url();
|
143 |
-
}
|
144 |
-
|
145 |
-
//Define
|
146 |
-
$js_array[$v] = array(
|
147 |
-
'the_hyperlink_text' => $the_hyperlink_text,
|
148 |
-
'registration_status' => $this->theme_user_registration[$v],
|
149 |
-
'is_commercial_plugin_tab' => $commercial_plugin_screen,
|
150 |
-
'registration_url' => $admin_url_passed . 'plugin-install.php?tab=commercial#installer_repo_' . $v
|
151 |
-
);
|
152 |
-
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
if ( !(empty($js_array)) ) {
|
157 |
-
wp_enqueue_script( 'installer-theme-install', WP_Installer()->res_url() . '/res/js/installer_theme_install.js', array('jquery', 'installer-admin'), WP_Installer()->version() );
|
158 |
-
$installer_ajax_url = admin_url( 'admin-ajax.php' );
|
159 |
-
|
160 |
-
if ( is_ssl() ) {
|
161 |
-
$installer_ajax_url = str_replace( 'http://', 'https://', $installer_ajax_url );
|
162 |
-
} else {
|
163 |
-
$installer_ajax_url = str_replace( 'https://', 'http://', $installer_ajax_url );
|
164 |
-
}
|
165 |
-
|
166 |
-
//Case where user is subscribed to a subscription that does not have themes
|
167 |
-
$subscription_js_check = $this->installer_theme_subscription_does_not_have_theme( $js_array );
|
168 |
-
|
169 |
-
wp_localize_script( 'installer-theme-install', 'installer_theme_install_localize',
|
170 |
-
array(
|
171 |
-
'js_array_installer' => $js_array,
|
172 |
-
'ajaxurl' => $installer_ajax_url,
|
173 |
-
'no_associated_themes' => $subscription_js_check,
|
174 |
-
'installer_theme_frontend_selected_tab_nonce' => wp_create_nonce( 'installer_theme_frontend_selected_tab' )
|
175 |
-
)
|
176 |
-
);
|
177 |
-
}
|
178 |
-
}
|
179 |
-
}
|
180 |
-
|
181 |
-
/** Case where user is subscribed to a subscription that does not have themes */
|
182 |
-
protected function installer_theme_subscription_does_not_have_theme( $js_array ) {
|
183 |
-
|
184 |
-
$any_subscription_has_theme = array();
|
185 |
-
$number_of_registrations = array();
|
186 |
-
|
187 |
-
//Step1, we looped through JS array
|
188 |
-
foreach ( $js_array as $repo_slug => $js_details ) {
|
189 |
-
|
190 |
-
//Step2, checked if user is registered
|
191 |
-
if ( isset($this->theme_user_registration[$repo_slug]) ) {
|
192 |
-
$registration_status = $this->theme_user_registration[$repo_slug];
|
193 |
-
if ( $registration_status ) {
|
194 |
-
|
195 |
-
//Registered
|
196 |
-
$number_of_registrations[] = $repo_slug;
|
197 |
-
|
198 |
-
//Step3, we checked if the $repo_slug has available theme
|
199 |
-
$themes_available = false;
|
200 |
-
if ( isset($this->installer_themes[$repo_slug]) ) {
|
201 |
-
$themes_available = $this->installer_themes[$repo_slug];
|
202 |
-
if ( !(empty($themes_available)) ) {
|
203 |
-
//This subscription has theme
|
204 |
-
$themes_available = true;
|
205 |
-
}
|
206 |
-
}
|
207 |
-
|
208 |
-
if ( $themes_available ) {
|
209 |
-
$any_subscription_has_theme[] = $repo_slug;
|
210 |
-
}
|
211 |
-
}
|
212 |
-
}
|
213 |
-
|
214 |
-
}
|
215 |
-
|
216 |
-
//Step4, we are done looping, check if there are any repos that have themes
|
217 |
-
if ( empty($registration_status) ) {
|
218 |
-
|
219 |
-
//No registration on any repos
|
220 |
-
return FALSE;
|
221 |
-
|
222 |
-
} elseif ( !(empty($registration_status)) ) {
|
223 |
-
|
224 |
-
//Has some registration on some repos
|
225 |
-
//We then checked if this user has any active subscriptions
|
226 |
-
if ( empty($any_subscription_has_theme) ) {
|
227 |
-
//No subscription
|
228 |
-
return TRUE;
|
229 |
-
} else {
|
230 |
-
//Has subscription found
|
231 |
-
return FALSE;
|
232 |
-
}
|
233 |
-
}
|
234 |
-
}
|
235 |
-
|
236 |
-
/** Check if its the commercial plugin screen */
|
237 |
-
private function installer_theme_is_commercial_plugin_screen( $current_screen ) {
|
238 |
-
$commercial = false;
|
239 |
-
if ( ('plugin-install' == $current_screen) || ('plugin-install-network' == $current_screen) ) {
|
240 |
-
if ( isset($_GET['tab']) ) {
|
241 |
-
$tab = $_GET['tab'];
|
242 |
-
if ( 'commercial' == $tab ) {
|
243 |
-
$commercial = true;
|
244 |
-
}
|
245 |
-
}
|
246 |
-
}
|
247 |
-
return $commercial;
|
248 |
-
}
|
249 |
-
|
250 |
-
/** Current screen */
|
251 |
-
private function installer_theme_current_screen() {
|
252 |
-
|
253 |
-
$current_screen_loaded = false;
|
254 |
-
|
255 |
-
if ( function_exists( 'get_current_screen' ) ) {
|
256 |
-
|
257 |
-
$screen_output = get_current_screen();
|
258 |
-
$current_screen_loaded = $screen_output->id;
|
259 |
-
|
260 |
-
}
|
261 |
-
|
262 |
-
return $current_screen_loaded;
|
263 |
-
|
264 |
-
}
|
265 |
-
|
266 |
-
/** Override WordPress Themes API */
|
267 |
-
public function installer_theme_api_override( $api_boolean, $action, $args ) {
|
268 |
-
|
269 |
-
//Let's checked if user is browsing our themes
|
270 |
-
if ( isset($args->browse) ) {
|
271 |
-
$browse = $args->browse;
|
272 |
-
if ( in_array( $browse, $this->theme_repo ) ) {
|
273 |
-
//Uniquely validated for our Themes
|
274 |
-
if ( 'query_themes' == $action ) {
|
275 |
-
//User is querying or asking information about our themes, let's override
|
276 |
-
$api_boolean = true;
|
277 |
-
}
|
278 |
-
}
|
279 |
-
} elseif ( isset($args->slug) ) {
|
280 |
-
//We are installing our themes
|
281 |
-
$theme_to_install = $args->slug;
|
282 |
-
|
283 |
-
//Lets uniquely validate if this belongs to us
|
284 |
-
//Check if this is OTGS theme
|
285 |
-
$validate_check = $this->installer_themes_belong_to_us( $theme_to_install );
|
286 |
-
if ( $validate_check ) {
|
287 |
-
//Belongs to us
|
288 |
-
if ( !(empty($theme_to_install)) ) {
|
289 |
-
$api_boolean = true;
|
290 |
-
}
|
291 |
-
}
|
292 |
-
}
|
293 |
-
|
294 |
-
return $api_boolean;
|
295 |
-
}
|
296 |
-
|
297 |
-
/** Override WordPress Themes API response with our own themes API*/
|
298 |
-
public function installer_theme_api_override_response( $res, $action, $args ) {
|
299 |
-
|
300 |
-
if ( true === $res ) {
|
301 |
-
if ( isset($args->browse) ) {
|
302 |
-
$browse = $args->browse;
|
303 |
-
if ( in_array( $browse, $this->theme_repo ) ) {
|
304 |
-
//Uniquely validated for our themes
|
305 |
-
if ( 'query_themes' == $action ) {
|
306 |
-
//Client querying OTGS themes
|
307 |
-
//Check for registration status
|
308 |
-
if ( isset($this->theme_user_registration[$browse]) ) {
|
309 |
-
//Set
|
310 |
-
if ( !($this->theme_user_registration[$browse]) ) {
|
311 |
-
//Not registered yet
|
312 |
-
$res = new stdClass();
|
313 |
-
$res->info = array();
|
314 |
-
$res->themes = array();
|
315 |
-
return $res;
|
316 |
-
} else {
|
317 |
-
//Registered
|
318 |
-
$themes = $this->installer_theme_get_themes( '', $browse );
|
319 |
-
$res = $this->installer_theme_format_response( $themes, $action );
|
320 |
-
}
|
321 |
-
}
|
322 |
-
}
|
323 |
-
}
|
324 |
-
} elseif ( isset($args->slug) ) {
|
325 |
-
//We are installing theme
|
326 |
-
//Lets uniquely validate if this belongs to our theme
|
327 |
-
$theme_to_install = $args->slug;
|
328 |
-
|
329 |
-
//Lets uniquely validate if this belongs to us
|
330 |
-
//Check if this is OTGS theme
|
331 |
-
$validate_check = $this->installer_themes_belong_to_us( $theme_to_install );
|
332 |
-
if ( $validate_check ) {
|
333 |
-
//Belongs to us
|
334 |
-
if ( ($res) && ('theme_information' == $action) ) {
|
335 |
-
$themes = $this->installer_theme_get_themes( '', $this->installer_theme_active_tab );
|
336 |
-
$res = $this->installer_theme_format_response( $themes, $action, $args->slug );
|
337 |
-
}
|
338 |
-
}
|
339 |
-
}
|
340 |
-
return $res;
|
341 |
-
} else {
|
342 |
-
//Default WP Themes here
|
343 |
-
$client_side_active_tab = get_option( 'wp_installer_clientside_active_tab' );
|
344 |
-
if ( $client_side_active_tab ) {
|
345 |
-
if ( !(in_array( $client_side_active_tab, $this->theme_repo )) ) {
|
346 |
-
//Not OTGS tab
|
347 |
-
return $res;
|
348 |
-
}
|
349 |
-
}
|
350 |
-
|
351 |
-
}
|
352 |
-
}
|
353 |
-
|
354 |
-
/** Get Themes */
|
355 |
-
private function installer_theme_get_themes( $product_url = '', $repo_source = '' ) {
|
356 |
-
|
357 |
-
//Query API
|
358 |
-
if ( empty($product_url) ) {
|
359 |
-
//Not set
|
360 |
-
if ( isset($this->repository_theme_products[$this->installer_theme_active_tab]) ) {
|
361 |
-
$query_remote_url = $this->repository_theme_products[$this->installer_theme_active_tab];
|
362 |
-
}
|
363 |
-
|
364 |
-
} else {
|
365 |
-
$query_remote_url = $product_url;
|
366 |
-
}
|
367 |
-
|
368 |
-
//Let's retrieved current installer settings so we won't be querying all the time
|
369 |
-
$current_installer_settings = WP_Installer()->get_settings();
|
370 |
-
|
371 |
-
//Set $themes to FALSE by default
|
372 |
-
$themes = false;
|
373 |
-
|
374 |
-
if ( (is_array( $current_installer_settings )) && (!(empty($current_installer_settings))) ) {
|
375 |
-
|
376 |
-
//Set and already defined, retrieved $products
|
377 |
-
if ( isset($current_installer_settings['repositories'][$repo_source]['data']) ) {
|
378 |
-
$products = $current_installer_settings['repositories'][$repo_source]['data'];
|
379 |
-
if ( isset($products['downloads']['themes']) ) {
|
380 |
-
$themes = $products['downloads']['themes'];
|
381 |
-
}
|
382 |
-
}
|
383 |
-
|
384 |
-
} else {
|
385 |
-
|
386 |
-
//Call API
|
387 |
-
$response = wp_remote_get( $query_remote_url );
|
388 |
-
|
389 |
-
if ( is_wp_error( $response ) ) {
|
390 |
-
//Error detected: http fallback
|
391 |
-
$query_remote_url = preg_replace( "@^https://@", 'http://', $query_remote_url );
|
392 |
-
$response = wp_remote_get( $query_remote_url );
|
393 |
-
}
|
394 |
-
|
395 |
-
if ( !(is_wp_error( $response )) ) {
|
396 |
-
//Not WP error
|
397 |
-
//Evaluate response
|
398 |
-
if ( $response && isset($response['response']['code']) && $response['response']['code'] == 200 ) {
|
399 |
-
//In this case, response is set and defined, proceed...
|
400 |
-
$body = wp_remote_retrieve_body( $response );
|
401 |
-
if ( $body ) {
|
402 |
-
$products = json_decode( $body, true );
|
403 |
-
if ( isset($products['downloads']['themes']) ) {
|
404 |
-
$themes = $products['downloads']['themes'];
|
405 |
-
}
|
406 |
-
}
|
407 |
-
|
408 |
-
}
|
409 |
-
}
|
410 |
-
}
|
411 |
-
|
412 |
-
//Return themes, can be filtered by user subscription type
|
413 |
-
return apply_filters( 'installer_theme_get_themes', $themes, $this->installer_theme_active_tab );
|
414 |
-
}
|
415 |
-
|
416 |
-
/** Format response in compatibility with WordPress Theme API response */
|
417 |
-
private function installer_theme_format_response( $themes, $action, $slug = '' ) {
|
418 |
-
|
419 |
-
//Let's append download link only when retrieving theme information for installation
|
420 |
-
if ( ('theme_information' == $action) && (!(empty($slug))) ) {
|
421 |
-
|
422 |
-
//Only return one result -> the theme to be installed
|
423 |
-
foreach ( $themes as $k => $theme ) {
|
424 |
-
if ( $slug == $theme['basename'] ) {
|
425 |
-
$theme['download_link'] = WP_Installer()->append_site_key_to_download_url( $theme['url'], $this->installer_site_key[$this->installer_theme_active_tab], $this->installer_theme_active_tab );
|
426 |
-
$theme = json_decode( json_encode( $theme ), FALSE );
|
427 |
-
return $theme;
|
428 |
-
}
|
429 |
-
}
|
430 |
-
|
431 |
-
} else {
|
432 |
-
|
433 |
-
$res = new stdClass();
|
434 |
-
$res->info = array();
|
435 |
-
$res->themes = array();
|
436 |
-
|
437 |
-
//Define info
|
438 |
-
$res->info['page'] = 1;
|
439 |
-
$res->info['pages'] = 10;
|
440 |
-
|
441 |
-
//Let's count available themes ;
|
442 |
-
$res->info['results'] = count( $themes );
|
443 |
-
|
444 |
-
//Let's saved themes for easy access later on
|
445 |
-
$this->installer_theme_savethemes_by_slug( $themes );
|
446 |
-
|
447 |
-
//Let's defined available themes
|
448 |
-
if ( isset($this->installer_theme_subscription_type) ) {
|
449 |
-
//Has subscription type defined, let's saved what is associated with this subscription
|
450 |
-
$this->installer_theme_available( $this->installer_theme_active_tab, $this->installer_theme_subscription_type );
|
451 |
-
} else {
|
452 |
-
$this->installer_theme_available( $this->installer_theme_active_tab );
|
453 |
-
}
|
454 |
-
|
455 |
-
//Let's add themes to the overriden WordPress API Theme response
|
456 |
-
/** Installer 1.7.6: Update to compatible data format response from WP Theme API */
|
457 |
-
$theme_compatible_array=array();
|
458 |
-
if ((is_array($themes))) {
|
459 |
-
foreach ($themes as $k=>$v) {
|
460 |
-
$theme_compatible_array[]=(object)($v);
|
461 |
-
}
|
462 |
-
}
|
463 |
-
$res->themes = $theme_compatible_array;
|
464 |
-
$res->themes = apply_filters( 'installer_theme_hook_response_theme', $res->themes );
|
465 |
-
return $res;
|
466 |
-
}
|
467 |
-
}
|
468 |
-
|
469 |
-
/** Let's save all available themes by its slug after any latest API query */
|
470 |
-
private function installer_theme_savethemes_by_slug( $themes, $doing_query = false ) {
|
471 |
-
|
472 |
-
if ( !($doing_query) ) {
|
473 |
-
$this->installer_themes[$this->installer_theme_active_tab] = array();
|
474 |
-
}
|
475 |
-
|
476 |
-
if ( !(empty($themes)) ) {
|
477 |
-
$themes_for_saving = array();
|
478 |
-
foreach ( $themes as $k => $theme ) {
|
479 |
-
if ( !($doing_query) ) {
|
480 |
-
if ( isset($theme['slug']) ) {
|
481 |
-
$theme_slug = $theme['slug'];
|
482 |
-
if ( !(empty($theme_slug)) ) {
|
483 |
-
$themes_for_saving[] = $theme_slug;
|
484 |
-
}
|
485 |
-
}
|
486 |
-
} else {
|
487 |
-
|
488 |
-
if ( ((isset($theme['slug'])) && (isset($theme['version'])) &&
|
489 |
-
(isset($theme['theme_page_url']))) && (isset($theme['url']))
|
490 |
-
) {
|
491 |
-
$theme_slug = $theme['slug'];
|
492 |
-
$theme_version = $theme['version'];
|
493 |
-
$theme_page_url = $theme['theme_page_url'];
|
494 |
-
$theme_url = $theme['url'];
|
495 |
-
if ( (!(empty($theme_slug))) && (!(empty($theme_version))) &&
|
496 |
-
(!(empty($theme_page_url))) && (!(empty($theme_url)))
|
497 |
-
) {
|
498 |
-
//$theme_slug is unique for every theme
|
499 |
-
$themes_for_saving[$theme_slug] = array(
|
500 |
-
'version' => $theme_version,
|
501 |
-
'theme_page_url' => $theme_page_url,
|
502 |
-
'url' => $theme_url
|
503 |
-
);
|
504 |
-
|
505 |
-
}
|
506 |
-
}
|
507 |
-
}
|
508 |
-
|
509 |
-
}
|
510 |
-
|
511 |
-
if ( !(empty($themes_for_saving)) ) {
|
512 |
-
//Has themes for saving
|
513 |
-
if ( !($doing_query) ) {
|
514 |
-
//Not doing query
|
515 |
-
$existing_themes = get_option( $this->installer_themes_option[$this->installer_theme_active_tab] );
|
516 |
-
if ( !($existing_themes) ) {
|
517 |
-
//Does not yet exists
|
518 |
-
delete_option( $this->installer_themes_option[$this->installer_theme_active_tab] );
|
519 |
-
update_option( $this->installer_themes_option[$this->installer_theme_active_tab], $themes_for_saving );
|
520 |
-
} else {
|
521 |
-
//exists, check if we need to update
|
522 |
-
if ( $existing_themes == $themes_for_saving ) {
|
523 |
-
//Equal, no need to update here
|
524 |
-
} else {
|
525 |
-
//Update
|
526 |
-
delete_option( $this->installer_themes_option[$this->installer_theme_active_tab] );
|
527 |
-
update_option( $this->installer_themes_option[$this->installer_theme_active_tab], $themes_for_saving );
|
528 |
-
}
|
529 |
-
}
|
530 |
-
} else {
|
531 |
-
//Used for query purposes only, don't save anything
|
532 |
-
return $themes_for_saving;
|
533 |
-
}
|
534 |
-
}
|
535 |
-
}
|
536 |
-
}
|
537 |
-
|
538 |
-
/** Available themes */
|
539 |
-
private function installer_theme_available( $repo, $subscription_type = '' ) {
|
540 |
-
|
541 |
-
$subscription_type = intval( $subscription_type );
|
542 |
-
if ( $subscription_type > 0 ) {
|
543 |
-
|
544 |
-
//Here we have a case of validated subscription
|
545 |
-
//We need to set themes that is available to this subscription
|
546 |
-
$themes_associated_with_subscription = $this->installer_themes[$repo] = $this->installer_theme_get_themes_by_subscription( $subscription_type, $repo );
|
547 |
-
if ( !(empty($themes_associated_with_subscription)) ) {
|
548 |
-
//Has themes
|
549 |
-
$this->installer_themes[$repo] = $themes_associated_with_subscription;
|
550 |
-
}
|
551 |
-
} else {
|
552 |
-
|
553 |
-
//Get themes
|
554 |
-
$this->installer_themes[$repo] = get_option( $this->installer_themes_option[$repo] );
|
555 |
-
}
|
556 |
-
}
|
557 |
-
|
558 |
-
/** Theme upgrade check */
|
559 |
-
public function installer_theme_upgrade_check( $the_value ) {
|
560 |
-
|
561 |
-
//Step1: Let's looped through repos with themes and check if we have updates available for them.
|
562 |
-
if ( (is_array( $this->installer_repo_with_themes )) && (!(empty($this->installer_repo_with_themes))) ) {
|
563 |
-
foreach ( $this->installer_repo_with_themes as $k => $repo_slug ) {
|
564 |
-
//Step2: Let's checked if we have update for this theme
|
565 |
-
$update_available = get_option( $this->installer_themes_available_updates[$repo_slug] );
|
566 |
-
if ( $update_available ) {
|
567 |
-
if ( (is_array( $update_available )) && (!(empty($update_available))) ) {
|
568 |
-
//Has updates available coming from this specific theme repo
|
569 |
-
//Let's loop through the themes that needs update
|
570 |
-
foreach ( $update_available as $theme_slug => $v ) {
|
571 |
-
//Add to response API
|
572 |
-
$the_value->response [$theme_slug] = array(
|
573 |
-
'theme' => $theme_slug,
|
574 |
-
'new_version' => $v['new_version'],
|
575 |
-
'url' => $v['url'],
|
576 |
-
'package' => $v['package']
|
577 |
-
);
|
578 |
-
}
|
579 |
-
}
|
580 |
-
}
|
581 |
-
}
|
582 |
-
}
|
583 |
-
//Return
|
584 |
-
return $the_value;
|
585 |
-
}
|
586 |
-
|
587 |
-
/** Return repositories that has themes */
|
588 |
-
private function installer_theme_reposities_that_has_themes( $repositories, $ret_value = true, $doing_api_query = false ) {
|
589 |
-
|
590 |
-
$repositories_with_themes = array();
|
591 |
-
|
592 |
-
if ( (is_array( $repositories )) && (!(empty($repositories))) ) {
|
593 |
-
|
594 |
-
//Let's checked if we have something before
|
595 |
-
$themes = get_option( 'installer_repositories_with_theme' );
|
596 |
-
|
597 |
-
if ( (!($themes)) || ($doing_api_query) ) {
|
598 |
-
//Not yet defined
|
599 |
-
//Loop through each repositories and check whether they have themes
|
600 |
-
foreach ( $repositories as $k => $v ) {
|
601 |
-
if ( isset($v['products']) ) {
|
602 |
-
$products_url = $v['products'];
|
603 |
-
$themes = $this->installer_theme_get_themes( $products_url, $k );
|
604 |
-
if ( (is_array( $themes )) && (!(empty($themes))) ) {
|
605 |
-
//Repo has themes
|
606 |
-
$repositories_with_themes[] = $k;
|
607 |
-
}
|
608 |
-
}
|
609 |
-
}
|
610 |
-
} else {
|
611 |
-
//Already set
|
612 |
-
$repositories_with_themes = $themes;
|
613 |
-
}
|
614 |
-
|
615 |
-
if ( (((is_array( $repositories_with_themes )) && (!(empty($repositories_with_themes)))) && (!($themes))) || ($doing_api_query) ) {
|
616 |
-
//Save to db
|
617 |
-
update_option( 'installer_repositories_with_theme', $repositories_with_themes );
|
618 |
-
}
|
619 |
-
}
|
620 |
-
|
621 |
-
if ( $ret_value ) {
|
622 |
-
return $repositories_with_themes;
|
623 |
-
}
|
624 |
-
|
625 |
-
}
|
626 |
-
|
627 |
-
/** When WordPress queries its own Themes API, we sync with our own */
|
628 |
-
public function installer_theme_sync_native_wp_api( $response, $responsetext, $class, $args, $url ) {
|
629 |
-
|
630 |
-
$api_native_string = 'api.wordpress.org/themes/';
|
631 |
-
if ( (strpos( $url, $api_native_string ) !== false) ) {
|
632 |
-
//WordPress is querying its own themes API
|
633 |
-
$installer_repositories = WP_Installer()->get_repositories();
|
634 |
-
|
635 |
-
//Query our own API and update repository values too
|
636 |
-
$this->installer_theme_reposities_that_has_themes( $installer_repositories, false, true );
|
637 |
-
}
|
638 |
-
}
|
639 |
-
|
640 |
-
/** Returns product name by theme repo slug */
|
641 |
-
private function installer_theme_get_repo_product_name( $theme_repo ) {
|
642 |
-
|
643 |
-
$theme_repo_name = false;
|
644 |
-
|
645 |
-
if ( isset(WP_Installer()->settings['repositories'][$theme_repo]['data']['product-name']) ) {
|
646 |
-
//Set
|
647 |
-
$prod_name = WP_Installer()->settings['repositories'][$theme_repo]['data']['product-name'];
|
648 |
-
if ( !(empty($prod_name)) ) {
|
649 |
-
$theme_repo_name = $prod_name;
|
650 |
-
}
|
651 |
-
} else {
|
652 |
-
//Not yet
|
653 |
-
if ( $theme_repo == $this->theme_repo ) {
|
654 |
-
$result = $this->installer_theme_general_api_query();
|
655 |
-
if ( isset($result['product-name']) ) {
|
656 |
-
$product_name = $result['product-name'];
|
657 |
-
if ( !(empty($product_name)) ) {
|
658 |
-
$theme_repo_name = $product_name;
|
659 |
-
}
|
660 |
-
}
|
661 |
-
}
|
662 |
-
}
|
663 |
-
|
664 |
-
return $theme_repo_name;
|
665 |
-
}
|
666 |
-
|
667 |
-
/** General query API method, returns $products */
|
668 |
-
private function installer_theme_general_api_query() {
|
669 |
-
$products = false;
|
670 |
-
$response = wp_remote_get( $this->repository_theme_products );
|
671 |
-
if ( !(is_wp_error( $response )) ) {
|
672 |
-
//Not WP error
|
673 |
-
//Evaluate response
|
674 |
-
if ( $response && isset($response['response']['code']) && $response['response']['code'] == 200 ) {
|
675 |
-
//In this case, response is set and defined, proceed...
|
676 |
-
$body = wp_remote_retrieve_body( $response );
|
677 |
-
if ( $body ) {
|
678 |
-
$result = json_decode( $body, true );
|
679 |
-
if ( (is_array( $result )) && (!(empty($result))) ) {
|
680 |
-
$products = $result;
|
681 |
-
}
|
682 |
-
}
|
683 |
-
|
684 |
-
}
|
685 |
-
}
|
686 |
-
|
687 |
-
return $products;
|
688 |
-
}
|
689 |
-
|
690 |
-
/** General method to check if themes are OTGS themes based on its slug*/
|
691 |
-
private function installer_themes_belong_to_us( $theme_slug ) {
|
692 |
-
|
693 |
-
$found = false;
|
694 |
-
$theme_slug = trim( $theme_slug );
|
695 |
-
|
696 |
-
foreach ( $this->installer_themes as $repo_with_theme => $themes ) {
|
697 |
-
foreach ( $themes as $k => $otgs_theme_slug ) {
|
698 |
-
if ( $theme_slug == $otgs_theme_slug ) {
|
699 |
-
//match found! Theme belongs to otgs
|
700 |
-
return true;
|
701 |
-
}
|
702 |
-
}
|
703 |
-
}
|
704 |
-
return $found;
|
705 |
-
|
706 |
-
}
|
707 |
-
|
708 |
-
/** Sets active tab on init */
|
709 |
-
public function installer_theme_sets_active_tab_on_init() {
|
710 |
-
|
711 |
-
if ( isset ($_SERVER ['REQUEST_URI']) ) {
|
712 |
-
$request_uri = $_SERVER ['REQUEST_URI'];
|
713 |
-
if ( isset ($_GET ['browse']) ) {
|
714 |
-
$active_tab =
|
715 |
-
$this->installer_theme_active_tab = $active_tab;
|
716 |
-
} elseif ( isset ($_POST ['request'] ['browse']) ) {
|
717 |
-
$active_tab =
|
718 |
-
$this->installer_theme_active_tab = $active_tab;
|
719 |
-
} elseif ( (isset ($_GET ['theme_repo'])) && (isset ($_GET ['action'])) ) {
|
720 |
-
$theme_repo =
|
721 |
-
$the_action =
|
722 |
-
if ( ('install-theme' == $the_action) && (!(empty($theme_repo))) ) {
|
723 |
-
$this->installer_theme_active_tab = $theme_repo;
|
724 |
-
}
|
725 |
-
} elseif ( wp_get_referer() ) {
|
726 |
-
$referer = wp_get_referer();
|
727 |
-
$parts = parse_url( $referer );
|
728 |
-
if ( isset($parts['query']) ) {
|
729 |
-
parse_str( $parts['query'], $query );
|
730 |
-
if ( isset($query['browse']) ) {
|
731 |
-
$this->installer_theme_active_tab = $query['browse'];
|
732 |
-
}
|
733 |
-
}
|
734 |
-
}
|
735 |
-
}
|
736 |
-
}
|
737 |
-
|
738 |
-
/** WP Theme API compatibility- added num ratings */
|
739 |
-
/** Installer 1.7.6+ Added updated 'rating' field */
|
740 |
-
public function installer_theme_add_num_ratings( $themes ) {
|
741 |
-
|
742 |
-
if ( (is_array( $themes )) && (!(empty($themes))) ) {
|
743 |
-
foreach ( $themes as $k => $v ) {
|
744 |
-
if ( !(isset($v->num_ratings)) ) {
|
745 |
-
$themes[$k]->num_ratings = 100;
|
746 |
-
}
|
747 |
-
if ( !(isset($v->rating)) ) {
|
748 |
-
$themes[$k]->rating = 100;
|
749 |
-
}
|
750 |
-
}
|
751 |
-
}
|
752 |
-
|
753 |
-
return $themes;
|
754 |
-
}
|
755 |
-
|
756 |
-
/** When WordPress.org makes a call to its repository, let's run our own upgrade checks too */
|
757 |
-
public function installer_theme_sync_call_wp_theme_api( $locales ) {
|
758 |
-
|
759 |
-
$this->installer_theme_upgrade_theme_check();
|
760 |
-
|
761 |
-
return $locales;
|
762 |
-
}
|
763 |
-
|
764 |
-
/** Upgrade theme check */
|
765 |
-
private function installer_theme_upgrade_theme_check() {
|
766 |
-
|
767 |
-
// Step1-> we get all installed themes in clients local themes directory
|
768 |
-
$installed_themes = wp_get_themes();
|
769 |
-
|
770 |
-
// Step2: We need to loop through each repository with themes
|
771 |
-
foreach ( $this->installer_repo_with_themes as $k => $repo_slug ) {
|
772 |
-
|
773 |
-
// We then need to retrieved the products URL for each of this repo
|
774 |
-
$products_url = $this->repository_theme_products [$repo_slug];
|
775 |
-
|
776 |
-
// Step3-> we get all available themes in our repository via API based on this URL
|
777 |
-
$available_themes = $this->installer_theme_get_themes( $products_url, $repo_slug );
|
778 |
-
|
779 |
-
if ( !($available_themes) ) {
|
780 |
-
|
781 |
-
// API is not available as of the moment, return..
|
782 |
-
return;
|
783 |
-
} else {
|
784 |
-
|
785 |
-
// We have available themes here...
|
786 |
-
// Step4->let's simplify available themes data by slugs
|
787 |
-
$simplified_available_themes = $this->installer_theme_savethemes_by_slug( $available_themes, true );
|
788 |
-
|
789 |
-
// Step5->Let's loop through installed themes
|
790 |
-
if ( (is_array( $installed_themes )) && (!(empty ($installed_themes))) ) {
|
791 |
-
$otgs_theme_updates_available = array();
|
792 |
-
foreach ( $installed_themes as $theme_slug => $theme_object ) {
|
793 |
-
if ( array_key_exists( $theme_slug, $simplified_available_themes ) ) {
|
794 |
-
|
795 |
-
// This is our theme
|
796 |
-
// Step6->Let's get version of the local theme installed
|
797 |
-
$local_version = $theme_object->get( 'Version' );
|
798 |
-
|
799 |
-
// Step7->Let's get the latest version of this theme, page URL and download URL from our repository
|
800 |
-
$repository_version = $simplified_available_themes [$theme_slug] ['version'];
|
801 |
-
$theme_page_url = $simplified_available_themes [$theme_slug] ['theme_page_url'];
|
802 |
-
$theme_download_url = $simplified_available_themes [$theme_slug] ['url'];
|
803 |
-
|
804 |
-
// Step8->Let's compare the version
|
805 |
-
if ( version_compare( $repository_version, $local_version, '>' ) ) {
|
806 |
-
|
807 |
-
// Update available for this theme
|
808 |
-
// Step9-> Define download URL with site key
|
809 |
-
$package_url = WP_Installer()->append_site_key_to_download_url( $theme_download_url, $this->installer_site_key [$repo_slug], $repo_slug );
|
810 |
-
|
811 |
-
//Step10-> Assign to updates array for later accessing.
|
812 |
-
$otgs_theme_updates_available[$theme_slug] = array(
|
813 |
-
'theme' => $theme_slug,
|
814 |
-
'new_version' => $repository_version,
|
815 |
-
'url' => $theme_page_url,
|
816 |
-
'package' => $package_url
|
817 |
-
);
|
818 |
-
}
|
819 |
-
}
|
820 |
-
}
|
821 |
-
//Exited the upgrade loop for this specific theme repository
|
822 |
-
if ( !(empty($otgs_theme_updates_available)) ) {
|
823 |
-
//Has updates
|
824 |
-
update_option( $this->installer_themes_available_updates[$repo_slug], $otgs_theme_updates_available );
|
825 |
-
} else {
|
826 |
-
//No updates
|
827 |
-
delete_option( $this->installer_themes_available_updates[$repo_slug] );
|
828 |
-
}
|
829 |
-
|
830 |
-
}
|
831 |
-
}
|
832 |
-
}
|
833 |
-
}
|
834 |
-
|
835 |
-
/** When the user is on Themes install page OTG themes repository, let's the currently selected tab */
|
836 |
-
public function installer_theme_add_query_arg_tab( $url, $path, $blog_id = null ) {
|
837 |
-
|
838 |
-
$wp_install_string = 'update.php?action=install-theme';
|
839 |
-
if ( $path == $wp_install_string ) {
|
840 |
-
if ( isset($this->installer_theme_active_tab) ) {
|
841 |
-
if ( !(empty($this->installer_theme_active_tab)) ) {
|
842 |
-
$url = add_query_arg( array(
|
843 |
-
'theme_repo' => $this->installer_theme_active_tab
|
844 |
-
), $url );
|
845 |
-
}
|
846 |
-
}
|
847 |
-
}
|
848 |
-
return $url;
|
849 |
-
}
|
850 |
-
|
851 |
-
/** Save frontend theme tab selected */
|
852 |
-
public function installer_theme_frontend_selected_tab() {
|
853 |
-
if ( isset($_POST["frontend_tab_selected"]) ) {
|
854 |
-
check_ajax_referer( 'installer_theme_frontend_selected_tab', 'installer_theme_frontend_selected_tab_nonce' );
|
855 |
-
|
856 |
-
//Client_side_active_tab
|
857 |
-
$frontend_tab_selected =
|
858 |
-
if ( !(empty($frontend_tab_selected)) ) {
|
859 |
-
//Front end tab selected
|
860 |
-
update_option( 'wp_installer_clientside_active_tab', $frontend_tab_selected, false );
|
861 |
-
|
862 |
-
//Check for registration status
|
863 |
-
if ( isset($this->theme_user_registration[$frontend_tab_selected]) ) {
|
864 |
-
//Set
|
865 |
-
if ( !($this->theme_user_registration[$frontend_tab_selected]) ) {
|
866 |
-
//Not registered yet
|
867 |
-
|
868 |
-
if ( is_multisite() ) {
|
869 |
-
$admin_url_passed = network_admin_url();
|
870 |
-
} else {
|
871 |
-
$admin_url_passed = admin_url();
|
872 |
-
}
|
873 |
-
|
874 |
-
$registration_url = $admin_url_passed . 'plugin-install.php?tab=commercial#installer_repo_' . $frontend_tab_selected;
|
875 |
-
|
876 |
-
//Message and link
|
877 |
-
$theme_repo_name = $this->installer_theme_get_repo_product_name( $frontend_tab_selected );;
|
878 |
-
$response['unregistered_messages'] = sprintf( __( 'To install and update %s, please %sregister%s %s for this site.', 'installer' ),
|
879 |
-
$theme_repo_name, '<a href="' . $registration_url . '">', '</a>', $theme_repo_name );
|
880 |
-
|
881 |
-
}
|
882 |
-
}
|
883 |
-
|
884 |
-
$response['output'] = $frontend_tab_selected;
|
885 |
-
echo json_encode( $response );
|
886 |
-
}
|
887 |
-
die();
|
888 |
-
}
|
889 |
-
die();
|
890 |
-
}
|
891 |
-
|
892 |
-
/** Installer loaded aux hooks */
|
893 |
-
public function installer_theme_loaded_hooks() {
|
894 |
-
|
895 |
-
if ( isset($this->installer_theme_subscription_type) ) {
|
896 |
-
$subscription_type = intval( $this->installer_theme_subscription_type );
|
897 |
-
if ( $subscription_type > 0 ) {
|
898 |
-
//Client is subscribed
|
899 |
-
add_filter( 'installer_theme_get_themes', array($this, 'installer_theme_filter_themes_by_subscription'), 10, 2 );
|
900 |
-
}
|
901 |
-
}
|
902 |
-
|
903 |
-
}
|
904 |
-
|
905 |
-
/** Get themes by subscription type */
|
906 |
-
protected function installer_theme_get_themes_by_subscription( $subscription_type, $repo ) {
|
907 |
-
|
908 |
-
$themes_associated_with_subscription = array();
|
909 |
-
if ( isset(WP_Installer()->settings['repositories'][$repo]['data']['packages']) ) {
|
910 |
-
//Set
|
911 |
-
$packages = WP_Installer()->settings['repositories'][$repo]['data']['packages'];
|
912 |
-
$available_themes_subscription = array();
|
913 |
-
foreach ( $packages as $package_id => $package_details ) {
|
914 |
-
if ( isset($package_details['products']) ) {
|
915 |
-
$the_products = $package_details['products'];
|
916 |
-
foreach ( $the_products as $product_slug => $product_details ) {
|
917 |
-
if ( isset($product_details['subscription_type']) ) {
|
918 |
-
$subscription_type_from_settings = intval( $product_details['subscription_type'] );
|
919 |
-
if ( $subscription_type_from_settings == $subscription_type ) {
|
920 |
-
//We found the subscription
|
921 |
-
if ( isset($product_details['themes']) ) {
|
922 |
-
$themes_associated_with_subscription = $product_details['themes'];
|
923 |
-
return $themes_associated_with_subscription;
|
924 |
-
}
|
925 |
-
}
|
926 |
-
}
|
927 |
-
|
928 |
-
}
|
929 |
-
}
|
930 |
-
}
|
931 |
-
}
|
932 |
-
return $themes_associated_with_subscription;
|
933 |
-
}
|
934 |
-
|
935 |
-
/** Filter API theme response according to user subscription */
|
936 |
-
public function installer_theme_filter_themes_by_subscription( $themes, $active_tab ) {
|
937 |
-
|
938 |
-
//Step1, we only filter OTGS themes
|
939 |
-
$orig = count( $themes );
|
940 |
-
if ( in_array( $active_tab, $this->theme_repo ) ) {
|
941 |
-
//OTGS Theme
|
942 |
-
//Step2, we retrieved the available themes based on client subscription
|
943 |
-
if ( isset($this->installer_themes[$active_tab]) ) {
|
944 |
-
$available_themes = $this->installer_themes[$active_tab];
|
945 |
-
//Step3, we filter $themes based on this info
|
946 |
-
if ( (is_array( $themes )) && (!(empty($themes))) ) {
|
947 |
-
foreach ( $themes as $k => $theme ) {
|
948 |
-
//Step4, get theme slug
|
949 |
-
if ( isset($theme['slug']) ) {
|
950 |
-
$theme_slug = $theme['slug'];
|
951 |
-
if ( !(empty($theme_slug)) ) {
|
952 |
-
if ( !(in_array( $theme_slug, $available_themes )) ) {
|
953 |
-
//This theme is not in available themes
|
954 |
-
unset($themes[$k]);
|
955 |
-
}
|
956 |
-
}
|
957 |
-
}
|
958 |
-
}
|
959 |
-
}
|
960 |
-
}
|
961 |
-
}
|
962 |
-
$new = count( $themes );
|
963 |
-
if ( $orig != $new ) {
|
964 |
-
//It is filtered
|
965 |
-
$themes = array_values( $themes );
|
966 |
-
}
|
967 |
-
|
968 |
-
return $themes;
|
969 |
-
}
|
970 |
-
|
971 |
-
/** Hook to wp_loaded, fires when all Installer theme class is ready */
|
972 |
-
public function installer_themes_support_set_up_func() {
|
973 |
-
do_action( 'installer_themes_support_set_up' );
|
974 |
-
}
|
975 |
-
|
976 |
-
}
|
977 |
-
|
978 |
-
/** Instantiate Installer Theme Class */
|
979 |
new Installer_Theme_Class;
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Installer Class for Theme Support
|
4 |
+
*
|
5 |
+
* Supports automatic updates and installation of Toolset/WPML Themes
|
6 |
+
*
|
7 |
+
* @class Installer_Theme_Class
|
8 |
+
* @version 1.6
|
9 |
+
* @category Class
|
10 |
+
* @author OnTheGoSystems
|
11 |
+
*/
|
12 |
+
|
13 |
+
if ( !defined( 'ABSPATH' ) ) {
|
14 |
+
exit;
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Installer_Theme_Class
|
19 |
+
*/
|
20 |
+
class Installer_Theme_Class {
|
21 |
+
|
22 |
+
/** Theme Repository */
|
23 |
+
private $theme_repo;
|
24 |
+
|
25 |
+
/** Repository API */
|
26 |
+
private $repository_api;
|
27 |
+
|
28 |
+
/** Repository Theme Products */
|
29 |
+
private $repository_theme_products;
|
30 |
+
|
31 |
+
/** Site URL */
|
32 |
+
private $installer_site_url;
|
33 |
+
|
34 |
+
/** Site Key */
|
35 |
+
private $installer_site_key;
|
36 |
+
|
37 |
+
/** The Themes Option */
|
38 |
+
protected $installer_themes_option;
|
39 |
+
|
40 |
+
/** Update settings */
|
41 |
+
protected $installer_themes_available_updates;
|
42 |
+
|
43 |
+
/** The Themes */
|
44 |
+
protected $installer_themes = array();
|
45 |
+
|
46 |
+
/** Repository with themes */
|
47 |
+
protected $installer_repo_with_themes;
|
48 |
+
|
49 |
+
/** Active tab */
|
50 |
+
protected $installer_theme_active_tab;
|
51 |
+
|
52 |
+
/** Theme user registration */
|
53 |
+
protected $theme_user_registration;
|
54 |
+
|
55 |
+
/** Client active subscription */
|
56 |
+
protected $installer_theme_subscription_type;
|
57 |
+
|
58 |
+
public function __construct() {
|
59 |
+
|
60 |
+
/** Properties */
|
61 |
+
|
62 |
+
//Get installer repositories
|
63 |
+
$installer_repositories = WP_Installer()->get_repositories();
|
64 |
+
|
65 |
+
//Get repos with themes
|
66 |
+
$repos_with_themes = $this->installer_theme_reposities_that_has_themes( $installer_repositories );
|
67 |
+
|
68 |
+
if ( is_array( $repos_with_themes ) ) {
|
69 |
+
//Assign to property
|
70 |
+
$this->installer_repo_with_themes = $repos_with_themes;
|
71 |
+
|
72 |
+
//Let's looped through repos with themes
|
73 |
+
foreach ( $repos_with_themes as $k => $repo ) {
|
74 |
+
|
75 |
+
//$repo could be 'toolset' or 'wpml'
|
76 |
+
//Assign each repo with theme to property
|
77 |
+
$this->theme_repo[] = $repo;
|
78 |
+
|
79 |
+
if ( (isset($installer_repositories[$repo]['api-url'])) && (isset($installer_repositories[$repo]['products'])) ) {
|
80 |
+
|
81 |
+
//Define the rest of the properties based on the given repo
|
82 |
+
$this->repository_api[$repo] = $installer_repositories[$repo]['api-url'];
|
83 |
+
$this->repository_theme_products[$repo] = $installer_repositories[$repo]['products'];
|
84 |
+
$this->installer_site_url[$repo] = WP_Installer()->get_installer_site_url( $repo );
|
85 |
+
$this->installer_site_key[$repo] = WP_Installer()->get_site_key( $repo );
|
86 |
+
$this->theme_user_registration[$repo] = false;
|
87 |
+
|
88 |
+
if ( WP_Installer()->repository_has_valid_subscription( $repo ) ) {
|
89 |
+
|
90 |
+
$this->installer_theme_subscription_type = WP_Installer()->get_subscription_type_for_repository( $repo );
|
91 |
+
$this->installer_themes_option[$repo] = 'wp_installer_' . $repo . '_themes';
|
92 |
+
$this->installer_themes_available_updates[$repo] = 'wp_installer_' . $repo . '_updated_themes';
|
93 |
+
$this->installer_theme_active_tab = '';
|
94 |
+
|
95 |
+
//We only set themes available to this validated subscription
|
96 |
+
$this->installer_theme_available( $repo, $this->installer_theme_subscription_type );
|
97 |
+
|
98 |
+
add_action( 'installer_themes_support_set_up', array($this, 'installer_theme_sets_active_tab_on_init'), 10 );
|
99 |
+
$this->theme_user_registration[$repo] = true;
|
100 |
+
}
|
101 |
+
|
102 |
+
/** We are ready.. let's initialize .... */
|
103 |
+
$this->init();
|
104 |
+
}
|
105 |
+
}
|
106 |
+
add_action( 'installer_themes_support_set_up', array($this, 'installer_theme_loaded_hooks') );
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
/** Init */
|
111 |
+
public function init() {
|
112 |
+
add_action( 'admin_enqueue_scripts', array($this, 'installer_theme_enqueue_scripts') );
|
113 |
+
add_filter( 'themes_api', array($this, 'installer_theme_api_override'), 10, 3 );
|
114 |
+
add_filter( 'themes_api_result', array($this, 'installer_theme_api_override_response'), 10, 3 );
|
115 |
+
add_filter( 'site_transient_update_themes', array($this, 'installer_theme_upgrade_check'), 10, 1 );
|
116 |
+
add_action( 'http_api_debug', array($this, 'installer_theme_sync_native_wp_api'), 10, 5 );
|
117 |
+
add_filter( 'installer_theme_hook_response_theme', array($this, 'installer_theme_add_num_ratings'), 10, 1 );
|
118 |
+
add_filter( 'themes_update_check_locales', array($this, 'installer_theme_sync_call_wp_theme_api'), 10, 1 );
|
119 |
+
add_filter( 'admin_url', array($this, 'installer_theme_add_query_arg_tab'), 10, 3 );
|
120 |
+
add_filter( 'network_admin_url', array($this, 'installer_theme_add_query_arg_tab'), 10, 2 );
|
121 |
+
add_action( 'wp_ajax_installer_theme_frontend_selected_tab', array($this, 'installer_theme_frontend_selected_tab'), 0 );
|
122 |
+
add_action( 'wp_loaded', array($this, 'installer_themes_support_set_up_func') );
|
123 |
+
}
|
124 |
+
|
125 |
+
/** Enqueue scripts */
|
126 |
+
public function installer_theme_enqueue_scripts() {
|
127 |
+
$current_screen = $this->installer_theme_current_screen();
|
128 |
+
$commercial_plugin_screen = $this->installer_theme_is_commercial_plugin_screen( $current_screen );
|
129 |
+
if ( ('theme-install' == $current_screen) || ($commercial_plugin_screen) || ('theme-install-network' == $current_screen) ) {
|
130 |
+
$repo_with_themes = $this->installer_repo_with_themes;
|
131 |
+
$js_array = array();
|
132 |
+
if ( is_array( $repo_with_themes ) ) {
|
133 |
+
foreach ( $repo_with_themes as $k => $v ) {
|
134 |
+
|
135 |
+
//Hyperlink text
|
136 |
+
$theme_repo_name = $this->installer_theme_get_repo_product_name( $v );
|
137 |
+
$the_hyperlink_text = esc_js( $theme_repo_name );
|
138 |
+
|
139 |
+
if ( is_multisite() ) {
|
140 |
+
$admin_url_passed = network_admin_url();
|
141 |
+
} else {
|
142 |
+
$admin_url_passed = admin_url();
|
143 |
+
}
|
144 |
+
|
145 |
+
//Define
|
146 |
+
$js_array[$v] = array(
|
147 |
+
'the_hyperlink_text' => $the_hyperlink_text,
|
148 |
+
'registration_status' => $this->theme_user_registration[$v],
|
149 |
+
'is_commercial_plugin_tab' => $commercial_plugin_screen,
|
150 |
+
'registration_url' => $admin_url_passed . 'plugin-install.php?tab=commercial#installer_repo_' . $v
|
151 |
+
);
|
152 |
+
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( !(empty($js_array)) ) {
|
157 |
+
wp_enqueue_script( 'installer-theme-install', WP_Installer()->res_url() . '/res/js/installer_theme_install.js', array('jquery', 'installer-admin'), WP_Installer()->version() );
|
158 |
+
$installer_ajax_url = admin_url( 'admin-ajax.php' );
|
159 |
+
|
160 |
+
if ( is_ssl() ) {
|
161 |
+
$installer_ajax_url = str_replace( 'http://', 'https://', $installer_ajax_url );
|
162 |
+
} else {
|
163 |
+
$installer_ajax_url = str_replace( 'https://', 'http://', $installer_ajax_url );
|
164 |
+
}
|
165 |
+
|
166 |
+
//Case where user is subscribed to a subscription that does not have themes
|
167 |
+
$subscription_js_check = $this->installer_theme_subscription_does_not_have_theme( $js_array );
|
168 |
+
|
169 |
+
wp_localize_script( 'installer-theme-install', 'installer_theme_install_localize',
|
170 |
+
array(
|
171 |
+
'js_array_installer' => $js_array,
|
172 |
+
'ajaxurl' => $installer_ajax_url,
|
173 |
+
'no_associated_themes' => $subscription_js_check,
|
174 |
+
'installer_theme_frontend_selected_tab_nonce' => wp_create_nonce( 'installer_theme_frontend_selected_tab' )
|
175 |
+
)
|
176 |
+
);
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
/** Case where user is subscribed to a subscription that does not have themes */
|
182 |
+
protected function installer_theme_subscription_does_not_have_theme( $js_array ) {
|
183 |
+
|
184 |
+
$any_subscription_has_theme = array();
|
185 |
+
$number_of_registrations = array();
|
186 |
+
|
187 |
+
//Step1, we looped through JS array
|
188 |
+
foreach ( $js_array as $repo_slug => $js_details ) {
|
189 |
+
|
190 |
+
//Step2, checked if user is registered
|
191 |
+
if ( isset($this->theme_user_registration[$repo_slug]) ) {
|
192 |
+
$registration_status = $this->theme_user_registration[$repo_slug];
|
193 |
+
if ( $registration_status ) {
|
194 |
+
|
195 |
+
//Registered
|
196 |
+
$number_of_registrations[] = $repo_slug;
|
197 |
+
|
198 |
+
//Step3, we checked if the $repo_slug has available theme
|
199 |
+
$themes_available = false;
|
200 |
+
if ( isset($this->installer_themes[$repo_slug]) ) {
|
201 |
+
$themes_available = $this->installer_themes[$repo_slug];
|
202 |
+
if ( !(empty($themes_available)) ) {
|
203 |
+
//This subscription has theme
|
204 |
+
$themes_available = true;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
if ( $themes_available ) {
|
209 |
+
$any_subscription_has_theme[] = $repo_slug;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
}
|
213 |
+
|
214 |
+
}
|
215 |
+
|
216 |
+
//Step4, we are done looping, check if there are any repos that have themes
|
217 |
+
if ( empty($registration_status) ) {
|
218 |
+
|
219 |
+
//No registration on any repos
|
220 |
+
return FALSE;
|
221 |
+
|
222 |
+
} elseif ( !(empty($registration_status)) ) {
|
223 |
+
|
224 |
+
//Has some registration on some repos
|
225 |
+
//We then checked if this user has any active subscriptions
|
226 |
+
if ( empty($any_subscription_has_theme) ) {
|
227 |
+
//No subscription
|
228 |
+
return TRUE;
|
229 |
+
} else {
|
230 |
+
//Has subscription found
|
231 |
+
return FALSE;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
/** Check if its the commercial plugin screen */
|
237 |
+
private function installer_theme_is_commercial_plugin_screen( $current_screen ) {
|
238 |
+
$commercial = false;
|
239 |
+
if ( ('plugin-install' == $current_screen) || ('plugin-install-network' == $current_screen) ) {
|
240 |
+
if ( isset($_GET['tab']) ) {
|
241 |
+
$tab = sanitize_text_field( $_GET['tab'] );
|
242 |
+
if ( 'commercial' == $tab ) {
|
243 |
+
$commercial = true;
|
244 |
+
}
|
245 |
+
}
|
246 |
+
}
|
247 |
+
return $commercial;
|
248 |
+
}
|
249 |
+
|
250 |
+
/** Current screen */
|
251 |
+
private function installer_theme_current_screen() {
|
252 |
+
|
253 |
+
$current_screen_loaded = false;
|
254 |
+
|
255 |
+
if ( function_exists( 'get_current_screen' ) ) {
|
256 |
+
|
257 |
+
$screen_output = get_current_screen();
|
258 |
+
$current_screen_loaded = $screen_output->id;
|
259 |
+
|
260 |
+
}
|
261 |
+
|
262 |
+
return $current_screen_loaded;
|
263 |
+
|
264 |
+
}
|
265 |
+
|
266 |
+
/** Override WordPress Themes API */
|
267 |
+
public function installer_theme_api_override( $api_boolean, $action, $args ) {
|
268 |
+
|
269 |
+
//Let's checked if user is browsing our themes
|
270 |
+
if ( isset($args->browse) ) {
|
271 |
+
$browse = $args->browse;
|
272 |
+
if ( in_array( $browse, $this->theme_repo ) ) {
|
273 |
+
//Uniquely validated for our Themes
|
274 |
+
if ( 'query_themes' == $action ) {
|
275 |
+
//User is querying or asking information about our themes, let's override
|
276 |
+
$api_boolean = true;
|
277 |
+
}
|
278 |
+
}
|
279 |
+
} elseif ( isset($args->slug) ) {
|
280 |
+
//We are installing our themes
|
281 |
+
$theme_to_install = $args->slug;
|
282 |
+
|
283 |
+
//Lets uniquely validate if this belongs to us
|
284 |
+
//Check if this is OTGS theme
|
285 |
+
$validate_check = $this->installer_themes_belong_to_us( $theme_to_install );
|
286 |
+
if ( $validate_check ) {
|
287 |
+
//Belongs to us
|
288 |
+
if ( !(empty($theme_to_install)) ) {
|
289 |
+
$api_boolean = true;
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}
|
293 |
+
|
294 |
+
return $api_boolean;
|
295 |
+
}
|
296 |
+
|
297 |
+
/** Override WordPress Themes API response with our own themes API*/
|
298 |
+
public function installer_theme_api_override_response( $res, $action, $args ) {
|
299 |
+
|
300 |
+
if ( true === $res ) {
|
301 |
+
if ( isset($args->browse) ) {
|
302 |
+
$browse = $args->browse;
|
303 |
+
if ( in_array( $browse, $this->theme_repo ) ) {
|
304 |
+
//Uniquely validated for our themes
|
305 |
+
if ( 'query_themes' == $action ) {
|
306 |
+
//Client querying OTGS themes
|
307 |
+
//Check for registration status
|
308 |
+
if ( isset($this->theme_user_registration[$browse]) ) {
|
309 |
+
//Set
|
310 |
+
if ( !($this->theme_user_registration[$browse]) ) {
|
311 |
+
//Not registered yet
|
312 |
+
$res = new stdClass();
|
313 |
+
$res->info = array();
|
314 |
+
$res->themes = array();
|
315 |
+
return $res;
|
316 |
+
} else {
|
317 |
+
//Registered
|
318 |
+
$themes = $this->installer_theme_get_themes( '', $browse );
|
319 |
+
$res = $this->installer_theme_format_response( $themes, $action );
|
320 |
+
}
|
321 |
+
}
|
322 |
+
}
|
323 |
+
}
|
324 |
+
} elseif ( isset($args->slug) ) {
|
325 |
+
//We are installing theme
|
326 |
+
//Lets uniquely validate if this belongs to our theme
|
327 |
+
$theme_to_install = $args->slug;
|
328 |
+
|
329 |
+
//Lets uniquely validate if this belongs to us
|
330 |
+
//Check if this is OTGS theme
|
331 |
+
$validate_check = $this->installer_themes_belong_to_us( $theme_to_install );
|
332 |
+
if ( $validate_check ) {
|
333 |
+
//Belongs to us
|
334 |
+
if ( ($res) && ('theme_information' == $action) ) {
|
335 |
+
$themes = $this->installer_theme_get_themes( '', $this->installer_theme_active_tab );
|
336 |
+
$res = $this->installer_theme_format_response( $themes, $action, $args->slug );
|
337 |
+
}
|
338 |
+
}
|
339 |
+
}
|
340 |
+
return $res;
|
341 |
+
} else {
|
342 |
+
//Default WP Themes here
|
343 |
+
$client_side_active_tab = get_option( 'wp_installer_clientside_active_tab' );
|
344 |
+
if ( $client_side_active_tab ) {
|
345 |
+
if ( !(in_array( $client_side_active_tab, $this->theme_repo )) ) {
|
346 |
+
//Not OTGS tab
|
347 |
+
return $res;
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
}
|
352 |
+
}
|
353 |
+
|
354 |
+
/** Get Themes */
|
355 |
+
private function installer_theme_get_themes( $product_url = '', $repo_source = '' ) {
|
356 |
+
|
357 |
+
//Query API
|
358 |
+
if ( empty($product_url) ) {
|
359 |
+
//Not set
|
360 |
+
if ( isset($this->repository_theme_products[$this->installer_theme_active_tab]) ) {
|
361 |
+
$query_remote_url = $this->repository_theme_products[$this->installer_theme_active_tab];
|
362 |
+
}
|
363 |
+
|
364 |
+
} else {
|
365 |
+
$query_remote_url = $product_url;
|
366 |
+
}
|
367 |
+
|
368 |
+
//Let's retrieved current installer settings so we won't be querying all the time
|
369 |
+
$current_installer_settings = WP_Installer()->get_settings();
|
370 |
+
|
371 |
+
//Set $themes to FALSE by default
|
372 |
+
$themes = false;
|
373 |
+
|
374 |
+
if ( (is_array( $current_installer_settings )) && (!(empty($current_installer_settings))) ) {
|
375 |
+
|
376 |
+
//Set and already defined, retrieved $products
|
377 |
+
if ( isset($current_installer_settings['repositories'][$repo_source]['data']) ) {
|
378 |
+
$products = $current_installer_settings['repositories'][$repo_source]['data'];
|
379 |
+
if ( isset($products['downloads']['themes']) ) {
|
380 |
+
$themes = $products['downloads']['themes'];
|
381 |
+
}
|
382 |
+
}
|
383 |
+
|
384 |
+
} else {
|
385 |
+
|
386 |
+
//Call API
|
387 |
+
$response = wp_remote_get( $query_remote_url );
|
388 |
+
|
389 |
+
if ( is_wp_error( $response ) ) {
|
390 |
+
//Error detected: http fallback
|
391 |
+
$query_remote_url = preg_replace( "@^https://@", 'http://', $query_remote_url );
|
392 |
+
$response = wp_remote_get( $query_remote_url );
|
393 |
+
}
|
394 |
+
|
395 |
+
if ( !(is_wp_error( $response )) ) {
|
396 |
+
//Not WP error
|
397 |
+
//Evaluate response
|
398 |
+
if ( $response && isset($response['response']['code']) && $response['response']['code'] == 200 ) {
|
399 |
+
//In this case, response is set and defined, proceed...
|
400 |
+
$body = wp_remote_retrieve_body( $response );
|
401 |
+
if ( $body ) {
|
402 |
+
$products = json_decode( $body, true );
|
403 |
+
if ( isset($products['downloads']['themes']) ) {
|
404 |
+
$themes = $products['downloads']['themes'];
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
}
|
409 |
+
}
|
410 |
+
}
|
411 |
+
|
412 |
+
//Return themes, can be filtered by user subscription type
|
413 |
+
return apply_filters( 'installer_theme_get_themes', $themes, $this->installer_theme_active_tab );
|
414 |
+
}
|
415 |
+
|
416 |
+
/** Format response in compatibility with WordPress Theme API response */
|
417 |
+
private function installer_theme_format_response( $themes, $action, $slug = '' ) {
|
418 |
+
|
419 |
+
//Let's append download link only when retrieving theme information for installation
|
420 |
+
if ( ('theme_information' == $action) && (!(empty($slug))) ) {
|
421 |
+
|
422 |
+
//Only return one result -> the theme to be installed
|
423 |
+
foreach ( $themes as $k => $theme ) {
|
424 |
+
if ( $slug == $theme['basename'] ) {
|
425 |
+
$theme['download_link'] = WP_Installer()->append_site_key_to_download_url( $theme['url'], $this->installer_site_key[$this->installer_theme_active_tab], $this->installer_theme_active_tab );
|
426 |
+
$theme = json_decode( json_encode( $theme ), FALSE );
|
427 |
+
return $theme;
|
428 |
+
}
|
429 |
+
}
|
430 |
+
|
431 |
+
} else {
|
432 |
+
|
433 |
+
$res = new stdClass();
|
434 |
+
$res->info = array();
|
435 |
+
$res->themes = array();
|
436 |
+
|
437 |
+
//Define info
|
438 |
+
$res->info['page'] = 1;
|
439 |
+
$res->info['pages'] = 10;
|
440 |
+
|
441 |
+
//Let's count available themes ;
|
442 |
+
$res->info['results'] = count( $themes );
|
443 |
+
|
444 |
+
//Let's saved themes for easy access later on
|
445 |
+
$this->installer_theme_savethemes_by_slug( $themes );
|
446 |
+
|
447 |
+
//Let's defined available themes
|
448 |
+
if ( isset($this->installer_theme_subscription_type) ) {
|
449 |
+
//Has subscription type defined, let's saved what is associated with this subscription
|
450 |
+
$this->installer_theme_available( $this->installer_theme_active_tab, $this->installer_theme_subscription_type );
|
451 |
+
} else {
|
452 |
+
$this->installer_theme_available( $this->installer_theme_active_tab );
|
453 |
+
}
|
454 |
+
|
455 |
+
//Let's add themes to the overriden WordPress API Theme response
|
456 |
+
/** Installer 1.7.6: Update to compatible data format response from WP Theme API */
|
457 |
+
$theme_compatible_array=array();
|
458 |
+
if ((is_array($themes))) {
|
459 |
+
foreach ($themes as $k=>$v) {
|
460 |
+
$theme_compatible_array[]=(object)($v);
|
461 |
+
}
|
462 |
+
}
|
463 |
+
$res->themes = $theme_compatible_array;
|
464 |
+
$res->themes = apply_filters( 'installer_theme_hook_response_theme', $res->themes );
|
465 |
+
return $res;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
|
469 |
+
/** Let's save all available themes by its slug after any latest API query */
|
470 |
+
private function installer_theme_savethemes_by_slug( $themes, $doing_query = false ) {
|
471 |
+
|
472 |
+
if ( !($doing_query) ) {
|
473 |
+
$this->installer_themes[$this->installer_theme_active_tab] = array();
|
474 |
+
}
|
475 |
+
|
476 |
+
if ( !(empty($themes)) ) {
|
477 |
+
$themes_for_saving = array();
|
478 |
+
foreach ( $themes as $k => $theme ) {
|
479 |
+
if ( !($doing_query) ) {
|
480 |
+
if ( isset($theme['slug']) ) {
|
481 |
+
$theme_slug = $theme['slug'];
|
482 |
+
if ( !(empty($theme_slug)) ) {
|
483 |
+
$themes_for_saving[] = $theme_slug;
|
484 |
+
}
|
485 |
+
}
|
486 |
+
} else {
|
487 |
+
|
488 |
+
if ( ((isset($theme['slug'])) && (isset($theme['version'])) &&
|
489 |
+
(isset($theme['theme_page_url']))) && (isset($theme['url']))
|
490 |
+
) {
|
491 |
+
$theme_slug = $theme['slug'];
|
492 |
+
$theme_version = $theme['version'];
|
493 |
+
$theme_page_url = $theme['theme_page_url'];
|
494 |
+
$theme_url = $theme['url'];
|
495 |
+
if ( (!(empty($theme_slug))) && (!(empty($theme_version))) &&
|
496 |
+
(!(empty($theme_page_url))) && (!(empty($theme_url)))
|
497 |
+
) {
|
498 |
+
//$theme_slug is unique for every theme
|
499 |
+
$themes_for_saving[$theme_slug] = array(
|
500 |
+
'version' => $theme_version,
|
501 |
+
'theme_page_url' => $theme_page_url,
|
502 |
+
'url' => $theme_url
|
503 |
+
);
|
504 |
+
|
505 |
+
}
|
506 |
+
}
|
507 |
+
}
|
508 |
+
|
509 |
+
}
|
510 |
+
|
511 |
+
if ( !(empty($themes_for_saving)) ) {
|
512 |
+
//Has themes for saving
|
513 |
+
if ( !($doing_query) ) {
|
514 |
+
//Not doing query
|
515 |
+
$existing_themes = get_option( $this->installer_themes_option[$this->installer_theme_active_tab] );
|
516 |
+
if ( !($existing_themes) ) {
|
517 |
+
//Does not yet exists
|
518 |
+
delete_option( $this->installer_themes_option[$this->installer_theme_active_tab] );
|
519 |
+
update_option( $this->installer_themes_option[$this->installer_theme_active_tab], $themes_for_saving );
|
520 |
+
} else {
|
521 |
+
//exists, check if we need to update
|
522 |
+
if ( $existing_themes == $themes_for_saving ) {
|
523 |
+
//Equal, no need to update here
|
524 |
+
} else {
|
525 |
+
//Update
|
526 |
+
delete_option( $this->installer_themes_option[$this->installer_theme_active_tab] );
|
527 |
+
update_option( $this->installer_themes_option[$this->installer_theme_active_tab], $themes_for_saving );
|
528 |
+
}
|
529 |
+
}
|
530 |
+
} else {
|
531 |
+
//Used for query purposes only, don't save anything
|
532 |
+
return $themes_for_saving;
|
533 |
+
}
|
534 |
+
}
|
535 |
+
}
|
536 |
+
}
|
537 |
+
|
538 |
+
/** Available themes */
|
539 |
+
private function installer_theme_available( $repo, $subscription_type = '' ) {
|
540 |
+
|
541 |
+
$subscription_type = intval( $subscription_type );
|
542 |
+
if ( $subscription_type > 0 ) {
|
543 |
+
|
544 |
+
//Here we have a case of validated subscription
|
545 |
+
//We need to set themes that is available to this subscription
|
546 |
+
$themes_associated_with_subscription = $this->installer_themes[$repo] = $this->installer_theme_get_themes_by_subscription( $subscription_type, $repo );
|
547 |
+
if ( !(empty($themes_associated_with_subscription)) ) {
|
548 |
+
//Has themes
|
549 |
+
$this->installer_themes[$repo] = $themes_associated_with_subscription;
|
550 |
+
}
|
551 |
+
} else {
|
552 |
+
|
553 |
+
//Get themes
|
554 |
+
$this->installer_themes[$repo] = get_option( $this->installer_themes_option[$repo] );
|
555 |
+
}
|
556 |
+
}
|
557 |
+
|
558 |
+
/** Theme upgrade check */
|
559 |
+
public function installer_theme_upgrade_check( $the_value ) {
|
560 |
+
|
561 |
+
//Step1: Let's looped through repos with themes and check if we have updates available for them.
|
562 |
+
if ( (is_array( $this->installer_repo_with_themes )) && (!(empty($this->installer_repo_with_themes))) ) {
|
563 |
+
foreach ( $this->installer_repo_with_themes as $k => $repo_slug ) {
|
564 |
+
//Step2: Let's checked if we have update for this theme
|
565 |
+
$update_available = get_option( $this->installer_themes_available_updates[$repo_slug] );
|
566 |
+
if ( $update_available ) {
|
567 |
+
if ( (is_array( $update_available )) && (!(empty($update_available))) ) {
|
568 |
+
//Has updates available coming from this specific theme repo
|
569 |
+
//Let's loop through the themes that needs update
|
570 |
+
foreach ( $update_available as $theme_slug => $v ) {
|
571 |
+
//Add to response API
|
572 |
+
$the_value->response [$theme_slug] = array(
|
573 |
+
'theme' => $theme_slug,
|
574 |
+
'new_version' => $v['new_version'],
|
575 |
+
'url' => $v['url'],
|
576 |
+
'package' => $v['package']
|
577 |
+
);
|
578 |
+
}
|
579 |
+
}
|
580 |
+
}
|
581 |
+
}
|
582 |
+
}
|
583 |
+
//Return
|
584 |
+
return $the_value;
|
585 |
+
}
|
586 |
+
|
587 |
+
/** Return repositories that has themes */
|
588 |
+
private function installer_theme_reposities_that_has_themes( $repositories, $ret_value = true, $doing_api_query = false ) {
|
589 |
+
|
590 |
+
$repositories_with_themes = array();
|
591 |
+
|
592 |
+
if ( (is_array( $repositories )) && (!(empty($repositories))) ) {
|
593 |
+
|
594 |
+
//Let's checked if we have something before
|
595 |
+
$themes = get_option( 'installer_repositories_with_theme' );
|
596 |
+
|
597 |
+
if ( (!($themes)) || ($doing_api_query) ) {
|
598 |
+
//Not yet defined
|
599 |
+
//Loop through each repositories and check whether they have themes
|
600 |
+
foreach ( $repositories as $k => $v ) {
|
601 |
+
if ( isset($v['products']) ) {
|
602 |
+
$products_url = $v['products'];
|
603 |
+
$themes = $this->installer_theme_get_themes( $products_url, $k );
|
604 |
+
if ( (is_array( $themes )) && (!(empty($themes))) ) {
|
605 |
+
//Repo has themes
|
606 |
+
$repositories_with_themes[] = $k;
|
607 |
+
}
|
608 |
+
}
|
609 |
+
}
|
610 |
+
} else {
|
611 |
+
//Already set
|
612 |
+
$repositories_with_themes = $themes;
|
613 |
+
}
|
614 |
+
|
615 |
+
if ( (((is_array( $repositories_with_themes )) && (!(empty($repositories_with_themes)))) && (!($themes))) || ($doing_api_query) ) {
|
616 |
+
//Save to db
|
617 |
+
update_option( 'installer_repositories_with_theme', $repositories_with_themes );
|
618 |
+
}
|
619 |
+
}
|
620 |
+
|
621 |
+
if ( $ret_value ) {
|
622 |
+
return $repositories_with_themes;
|
623 |
+
}
|
624 |
+
|
625 |
+
}
|
626 |
+
|
627 |
+
/** When WordPress queries its own Themes API, we sync with our own */
|
628 |
+
public function installer_theme_sync_native_wp_api( $response, $responsetext, $class, $args, $url ) {
|
629 |
+
|
630 |
+
$api_native_string = 'api.wordpress.org/themes/';
|
631 |
+
if ( (strpos( $url, $api_native_string ) !== false) ) {
|
632 |
+
//WordPress is querying its own themes API
|
633 |
+
$installer_repositories = WP_Installer()->get_repositories();
|
634 |
+
|
635 |
+
//Query our own API and update repository values too
|
636 |
+
$this->installer_theme_reposities_that_has_themes( $installer_repositories, false, true );
|
637 |
+
}
|
638 |
+
}
|
639 |
+
|
640 |
+
/** Returns product name by theme repo slug */
|
641 |
+
private function installer_theme_get_repo_product_name( $theme_repo ) {
|
642 |
+
|
643 |
+
$theme_repo_name = false;
|
644 |
+
|
645 |
+
if ( isset(WP_Installer()->settings['repositories'][$theme_repo]['data']['product-name']) ) {
|
646 |
+
//Set
|
647 |
+
$prod_name = WP_Installer()->settings['repositories'][$theme_repo]['data']['product-name'];
|
648 |
+
if ( !(empty($prod_name)) ) {
|
649 |
+
$theme_repo_name = $prod_name;
|
650 |
+
}
|
651 |
+
} else {
|
652 |
+
//Not yet
|
653 |
+
if ( $theme_repo == $this->theme_repo ) {
|
654 |
+
$result = $this->installer_theme_general_api_query();
|
655 |
+
if ( isset($result['product-name']) ) {
|
656 |
+
$product_name = $result['product-name'];
|
657 |
+
if ( !(empty($product_name)) ) {
|
658 |
+
$theme_repo_name = $product_name;
|
659 |
+
}
|
660 |
+
}
|
661 |
+
}
|
662 |
+
}
|
663 |
+
|
664 |
+
return $theme_repo_name;
|
665 |
+
}
|
666 |
+
|
667 |
+
/** General query API method, returns $products */
|
668 |
+
private function installer_theme_general_api_query() {
|
669 |
+
$products = false;
|
670 |
+
$response = wp_remote_get( $this->repository_theme_products );
|
671 |
+
if ( !(is_wp_error( $response )) ) {
|
672 |
+
//Not WP error
|
673 |
+
//Evaluate response
|
674 |
+
if ( $response && isset($response['response']['code']) && $response['response']['code'] == 200 ) {
|
675 |
+
//In this case, response is set and defined, proceed...
|
676 |
+
$body = wp_remote_retrieve_body( $response );
|
677 |
+
if ( $body ) {
|
678 |
+
$result = json_decode( $body, true );
|
679 |
+
if ( (is_array( $result )) && (!(empty($result))) ) {
|
680 |
+
$products = $result;
|
681 |
+
}
|
682 |
+
}
|
683 |
+
|
684 |
+
}
|
685 |
+
}
|
686 |
+
|
687 |
+
return $products;
|
688 |
+
}
|
689 |
+
|
690 |
+
/** General method to check if themes are OTGS themes based on its slug*/
|
691 |
+
private function installer_themes_belong_to_us( $theme_slug ) {
|
692 |
+
|
693 |
+
$found = false;
|
694 |
+
$theme_slug = trim( $theme_slug );
|
695 |
+
|
696 |
+
foreach ( $this->installer_themes as $repo_with_theme => $themes ) {
|
697 |
+
foreach ( $themes as $k => $otgs_theme_slug ) {
|
698 |
+
if ( $theme_slug == $otgs_theme_slug ) {
|
699 |
+
//match found! Theme belongs to otgs
|
700 |
+
return true;
|
701 |
+
}
|
702 |
+
}
|
703 |
+
}
|
704 |
+
return $found;
|
705 |
+
|
706 |
+
}
|
707 |
+
|
708 |
+
/** Sets active tab on init */
|
709 |
+
public function installer_theme_sets_active_tab_on_init() {
|
710 |
+
|
711 |
+
if ( isset ($_SERVER ['REQUEST_URI']) ) {
|
712 |
+
$request_uri = $_SERVER ['REQUEST_URI'];
|
713 |
+
if ( isset ($_GET ['browse']) ) {
|
714 |
+
$active_tab = sanitize_text_field( $_GET['browse'] );
|
715 |
+
$this->installer_theme_active_tab = $active_tab;
|
716 |
+
} elseif ( isset ($_POST ['request'] ['browse']) ) {
|
717 |
+
$active_tab = sanitize_text_field ( $_POST['request']['browse'] );
|
718 |
+
$this->installer_theme_active_tab = $active_tab;
|
719 |
+
} elseif ( (isset ($_GET ['theme_repo'])) && (isset ($_GET ['action'])) ) {
|
720 |
+
$theme_repo = sanitize_text_field( $_GET['theme_repo'] );
|
721 |
+
$the_action = sanitize_text_field( $_GET['action'] );
|
722 |
+
if ( ('install-theme' == $the_action) && (!(empty($theme_repo))) ) {
|
723 |
+
$this->installer_theme_active_tab = $theme_repo;
|
724 |
+
}
|
725 |
+
} elseif ( wp_get_referer() ) {
|
726 |
+
$referer = wp_get_referer();
|
727 |
+
$parts = parse_url( $referer );
|
728 |
+
if ( isset($parts['query']) ) {
|
729 |
+
parse_str( $parts['query'], $query );
|
730 |
+
if ( isset($query['browse']) ) {
|
731 |
+
$this->installer_theme_active_tab = $query['browse'];
|
732 |
+
}
|
733 |
+
}
|
734 |
+
}
|
735 |
+
}
|
736 |
+
}
|
737 |
+
|
738 |
+
/** WP Theme API compatibility- added num ratings */
|
739 |
+
/** Installer 1.7.6+ Added updated 'rating' field */
|
740 |
+
public function installer_theme_add_num_ratings( $themes ) {
|
741 |
+
|
742 |
+
if ( (is_array( $themes )) && (!(empty($themes))) ) {
|
743 |
+
foreach ( $themes as $k => $v ) {
|
744 |
+
if ( !(isset($v->num_ratings)) ) {
|
745 |
+
$themes[$k]->num_ratings = 100;
|
746 |
+
}
|
747 |
+
if ( !(isset($v->rating)) ) {
|
748 |
+
$themes[$k]->rating = 100;
|
749 |
+
}
|
750 |
+
}
|
751 |
+
}
|
752 |
+
|
753 |
+
return $themes;
|
754 |
+
}
|
755 |
+
|
756 |
+
/** When WordPress.org makes a call to its repository, let's run our own upgrade checks too */
|
757 |
+
public function installer_theme_sync_call_wp_theme_api( $locales ) {
|
758 |
+
|
759 |
+
$this->installer_theme_upgrade_theme_check();
|
760 |
+
|
761 |
+
return $locales;
|
762 |
+
}
|
763 |
+
|
764 |
+
/** Upgrade theme check */
|
765 |
+
private function installer_theme_upgrade_theme_check() {
|
766 |
+
|
767 |
+
// Step1-> we get all installed themes in clients local themes directory
|
768 |
+
$installed_themes = wp_get_themes();
|
769 |
+
|
770 |
+
// Step2: We need to loop through each repository with themes
|
771 |
+
foreach ( $this->installer_repo_with_themes as $k => $repo_slug ) {
|
772 |
+
|
773 |
+
// We then need to retrieved the products URL for each of this repo
|
774 |
+
$products_url = $this->repository_theme_products [$repo_slug];
|
775 |
+
|
776 |
+
// Step3-> we get all available themes in our repository via API based on this URL
|
777 |
+
$available_themes = $this->installer_theme_get_themes( $products_url, $repo_slug );
|
778 |
+
|
779 |
+
if ( !($available_themes) ) {
|
780 |
+
|
781 |
+
// API is not available as of the moment, return..
|
782 |
+
return;
|
783 |
+
} else {
|
784 |
+
|
785 |
+
// We have available themes here...
|
786 |
+
// Step4->let's simplify available themes data by slugs
|
787 |
+
$simplified_available_themes = $this->installer_theme_savethemes_by_slug( $available_themes, true );
|
788 |
+
|
789 |
+
// Step5->Let's loop through installed themes
|
790 |
+
if ( (is_array( $installed_themes )) && (!(empty ($installed_themes))) ) {
|
791 |
+
$otgs_theme_updates_available = array();
|
792 |
+
foreach ( $installed_themes as $theme_slug => $theme_object ) {
|
793 |
+
if ( array_key_exists( $theme_slug, $simplified_available_themes ) ) {
|
794 |
+
|
795 |
+
// This is our theme
|
796 |
+
// Step6->Let's get version of the local theme installed
|
797 |
+
$local_version = $theme_object->get( 'Version' );
|
798 |
+
|
799 |
+
// Step7->Let's get the latest version of this theme, page URL and download URL from our repository
|
800 |
+
$repository_version = $simplified_available_themes [$theme_slug] ['version'];
|
801 |
+
$theme_page_url = $simplified_available_themes [$theme_slug] ['theme_page_url'];
|
802 |
+
$theme_download_url = $simplified_available_themes [$theme_slug] ['url'];
|
803 |
+
|
804 |
+
// Step8->Let's compare the version
|
805 |
+
if ( version_compare( $repository_version, $local_version, '>' ) ) {
|
806 |
+
|
807 |
+
// Update available for this theme
|
808 |
+
// Step9-> Define download URL with site key
|
809 |
+
$package_url = WP_Installer()->append_site_key_to_download_url( $theme_download_url, $this->installer_site_key [$repo_slug], $repo_slug );
|
810 |
+
|
811 |
+
//Step10-> Assign to updates array for later accessing.
|
812 |
+
$otgs_theme_updates_available[$theme_slug] = array(
|
813 |
+
'theme' => $theme_slug,
|
814 |
+
'new_version' => $repository_version,
|
815 |
+
'url' => $theme_page_url,
|
816 |
+
'package' => $package_url
|
817 |
+
);
|
818 |
+
}
|
819 |
+
}
|
820 |
+
}
|
821 |
+
//Exited the upgrade loop for this specific theme repository
|
822 |
+
if ( !(empty($otgs_theme_updates_available)) ) {
|
823 |
+
//Has updates
|
824 |
+
update_option( $this->installer_themes_available_updates[$repo_slug], $otgs_theme_updates_available );
|
825 |
+
} else {
|
826 |
+
//No updates
|
827 |
+
delete_option( $this->installer_themes_available_updates[$repo_slug] );
|
828 |
+
}
|
829 |
+
|
830 |
+
}
|
831 |
+
}
|
832 |
+
}
|
833 |
+
}
|
834 |
+
|
835 |
+
/** When the user is on Themes install page OTG themes repository, let's the currently selected tab */
|
836 |
+
public function installer_theme_add_query_arg_tab( $url, $path, $blog_id = null ) {
|
837 |
+
|
838 |
+
$wp_install_string = 'update.php?action=install-theme';
|
839 |
+
if ( $path == $wp_install_string ) {
|
840 |
+
if ( isset($this->installer_theme_active_tab) ) {
|
841 |
+
if ( !(empty($this->installer_theme_active_tab)) ) {
|
842 |
+
$url = add_query_arg( array(
|
843 |
+
'theme_repo' => $this->installer_theme_active_tab
|
844 |
+
), $url );
|
845 |
+
}
|
846 |
+
}
|
847 |
+
}
|
848 |
+
return $url;
|
849 |
+
}
|
850 |
+
|
851 |
+
/** Save frontend theme tab selected */
|
852 |
+
public function installer_theme_frontend_selected_tab() {
|
853 |
+
if ( isset($_POST["frontend_tab_selected"]) ) {
|
854 |
+
check_ajax_referer( 'installer_theme_frontend_selected_tab', 'installer_theme_frontend_selected_tab_nonce' );
|
855 |
+
|
856 |
+
//Client_side_active_tab
|
857 |
+
$frontend_tab_selected = sanitize_text_field( $_POST['frontend_tab_selected'] );
|
858 |
+
if ( !(empty($frontend_tab_selected)) ) {
|
859 |
+
//Front end tab selected
|
860 |
+
update_option( 'wp_installer_clientside_active_tab', $frontend_tab_selected, false );
|
861 |
+
|
862 |
+
//Check for registration status
|
863 |
+
if ( isset($this->theme_user_registration[$frontend_tab_selected]) ) {
|
864 |
+
//Set
|
865 |
+
if ( !($this->theme_user_registration[$frontend_tab_selected]) ) {
|
866 |
+
//Not registered yet
|
867 |
+
|
868 |
+
if ( is_multisite() ) {
|
869 |
+
$admin_url_passed = network_admin_url();
|
870 |
+
} else {
|
871 |
+
$admin_url_passed = admin_url();
|
872 |
+
}
|
873 |
+
|
874 |
+
$registration_url = $admin_url_passed . 'plugin-install.php?tab=commercial#installer_repo_' . $frontend_tab_selected;
|
875 |
+
|
876 |
+
//Message and link
|
877 |
+
$theme_repo_name = $this->installer_theme_get_repo_product_name( $frontend_tab_selected );;
|
878 |
+
$response['unregistered_messages'] = sprintf( __( 'To install and update %s, please %sregister%s %s for this site.', 'installer' ),
|
879 |
+
$theme_repo_name, '<a href="' . $registration_url . '">', '</a>', $theme_repo_name );
|
880 |
+
|
881 |
+
}
|
882 |
+
}
|
883 |
+
|
884 |
+
$response['output'] = $frontend_tab_selected;
|
885 |
+
echo json_encode( $response );
|
886 |
+
}
|
887 |
+
die();
|
888 |
+
}
|
889 |
+
die();
|
890 |
+
}
|
891 |
+
|
892 |
+
/** Installer loaded aux hooks */
|
893 |
+
public function installer_theme_loaded_hooks() {
|
894 |
+
|
895 |
+
if ( isset($this->installer_theme_subscription_type) ) {
|
896 |
+
$subscription_type = intval( $this->installer_theme_subscription_type );
|
897 |
+
if ( $subscription_type > 0 ) {
|
898 |
+
//Client is subscribed
|
899 |
+
add_filter( 'installer_theme_get_themes', array($this, 'installer_theme_filter_themes_by_subscription'), 10, 2 );
|
900 |
+
}
|
901 |
+
}
|
902 |
+
|
903 |
+
}
|
904 |
+
|
905 |
+
/** Get themes by subscription type */
|
906 |
+
protected function installer_theme_get_themes_by_subscription( $subscription_type, $repo ) {
|
907 |
+
|
908 |
+
$themes_associated_with_subscription = array();
|
909 |
+
if ( isset(WP_Installer()->settings['repositories'][$repo]['data']['packages']) ) {
|
910 |
+
//Set
|
911 |
+
$packages = WP_Installer()->settings['repositories'][$repo]['data']['packages'];
|
912 |
+
$available_themes_subscription = array();
|
913 |
+
foreach ( $packages as $package_id => $package_details ) {
|
914 |
+
if ( isset($package_details['products']) ) {
|
915 |
+
$the_products = $package_details['products'];
|
916 |
+
foreach ( $the_products as $product_slug => $product_details ) {
|
917 |
+
if ( isset($product_details['subscription_type']) ) {
|
918 |
+
$subscription_type_from_settings = intval( $product_details['subscription_type'] );
|
919 |
+
if ( $subscription_type_from_settings == $subscription_type ) {
|
920 |
+
//We found the subscription
|
921 |
+
if ( isset($product_details['themes']) ) {
|
922 |
+
$themes_associated_with_subscription = $product_details['themes'];
|
923 |
+
return $themes_associated_with_subscription;
|
924 |
+
}
|
925 |
+
}
|
926 |
+
}
|
927 |
+
|
928 |
+
}
|
929 |
+
}
|
930 |
+
}
|
931 |
+
}
|
932 |
+
return $themes_associated_with_subscription;
|
933 |
+
}
|
934 |
+
|
935 |
+
/** Filter API theme response according to user subscription */
|
936 |
+
public function installer_theme_filter_themes_by_subscription( $themes, $active_tab ) {
|
937 |
+
|
938 |
+
//Step1, we only filter OTGS themes
|
939 |
+
$orig = count( $themes );
|
940 |
+
if ( in_array( $active_tab, $this->theme_repo ) ) {
|
941 |
+
//OTGS Theme
|
942 |
+
//Step2, we retrieved the available themes based on client subscription
|
943 |
+
if ( isset($this->installer_themes[$active_tab]) ) {
|
944 |
+
$available_themes = $this->installer_themes[$active_tab];
|
945 |
+
//Step3, we filter $themes based on this info
|
946 |
+
if ( (is_array( $themes )) && (!(empty($themes))) ) {
|
947 |
+
foreach ( $themes as $k => $theme ) {
|
948 |
+
//Step4, get theme slug
|
949 |
+
if ( isset($theme['slug']) ) {
|
950 |
+
$theme_slug = $theme['slug'];
|
951 |
+
if ( !(empty($theme_slug)) ) {
|
952 |
+
if ( !(in_array( $theme_slug, $available_themes )) ) {
|
953 |
+
//This theme is not in available themes
|
954 |
+
unset($themes[$k]);
|
955 |
+
}
|
956 |
+
}
|
957 |
+
}
|
958 |
+
}
|
959 |
+
}
|
960 |
+
}
|
961 |
+
}
|
962 |
+
$new = count( $themes );
|
963 |
+
if ( $orig != $new ) {
|
964 |
+
//It is filtered
|
965 |
+
$themes = array_values( $themes );
|
966 |
+
}
|
967 |
+
|
968 |
+
return $themes;
|
969 |
+
}
|
970 |
+
|
971 |
+
/** Hook to wp_loaded, fires when all Installer theme class is ready */
|
972 |
+
public function installer_themes_support_set_up_func() {
|
973 |
+
do_action( 'installer_themes_support_set_up' );
|
974 |
+
}
|
975 |
+
|
976 |
+
}
|
977 |
+
|
978 |
+
/** Instantiate Installer Theme Class */
|
979 |
new Installer_Theme_Class;
|
library/otgs/installer/includes/installer-api.php
CHANGED
@@ -1,116 +1,116 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class WP_Installer_API{
|
4 |
-
|
5 |
-
public static function get_product_installer_link($repository_id, $package_id = false){
|
6 |
-
|
7 |
-
$menu_url = WP_Installer()->menu_url();
|
8 |
-
|
9 |
-
$url = $menu_url . '#' . $repository_id;
|
10 |
-
if($package_id){
|
11 |
-
$url .= '/' . $package_id;
|
12 |
-
}
|
13 |
-
|
14 |
-
return $url;
|
15 |
-
|
16 |
-
}
|
17 |
-
|
18 |
-
public static function get_product_price($repository_id, $package_id, $product_id, $incl_discount = false){
|
19 |
-
|
20 |
-
$price = WP_Installer()->get_product_price($repository_id, $package_id, $product_id, $incl_discount);
|
21 |
-
|
22 |
-
return $price;
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Retrieve the preferred translation service.
|
27 |
-
*
|
28 |
-
* @since 1.6.5
|
29 |
-
*
|
30 |
-
* @param string The repository id (e.g. wpml)
|
31 |
-
* @return string The translation service id
|
32 |
-
*/
|
33 |
-
public static function get_preferred_ts($repository_id = 'wpml'){
|
34 |
-
|
35 |
-
if(isset(WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'])){
|
36 |
-
return WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'];
|
37 |
-
}
|
38 |
-
|
39 |
-
return false;
|
40 |
-
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Set the preferred translation service.
|
45 |
-
*
|
46 |
-
* @since 1.6.5
|
47 |
-
*
|
48 |
-
* @param string The translation service id
|
49 |
-
* @param string The repository id (e.g. wpml)
|
50 |
-
*/
|
51 |
-
public static function set_preferred_ts( $value, $repository_id = 'wpml' ){
|
52 |
-
|
53 |
-
if( isset( WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'] ) ){
|
54 |
-
|
55 |
-
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'] = $value;
|
56 |
-
|
57 |
-
WP_Installer()->save_settings();
|
58 |
-
|
59 |
-
}
|
60 |
-
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Retrieve the referring translation service (if any)
|
65 |
-
*
|
66 |
-
* @since 1.6.5
|
67 |
-
*
|
68 |
-
* @param string The repository id (e.g. wpml)
|
69 |
-
* @return string The translation service id or false
|
70 |
-
*/
|
71 |
-
public static function get_ts_referal($repository_id = 'wpml'){
|
72 |
-
|
73 |
-
if(isset(WP_Installer()->settings['repositories'][$repository_id]['ts_info']['referal'])){
|
74 |
-
return WP_Installer()->settings['repositories'][$repository_id]['ts_info']['referal'];
|
75 |
-
}
|
76 |
-
|
77 |
-
return false;
|
78 |
-
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Retrieve the translation services client id for a specific repository (if any)
|
83 |
-
*
|
84 |
-
* @since 1.7.9
|
85 |
-
*
|
86 |
-
* @param string The repository id (e.g. wpml)
|
87 |
-
* @return string The client id or false
|
88 |
-
*/
|
89 |
-
public static function get_ts_client_id( $repository_id = 'wpml' ){
|
90 |
-
|
91 |
-
if(isset(WP_Installer()->settings['repositories'][$repository_id]['ts_info']['client_id'])){
|
92 |
-
return WP_Installer()->settings['repositories'][$repository_id]['ts_info']['client_id'];
|
93 |
-
}
|
94 |
-
|
95 |
-
return false;
|
96 |
-
|
97 |
-
}
|
98 |
-
|
99 |
-
/**
|
100 |
-
* Retrieve the site key corresponding to a repository.
|
101 |
-
* This is a wrapper of WP_Installer::get_site_key()
|
102 |
-
* @see WP_Installer::get_site_key()
|
103 |
-
*
|
104 |
-
* @since 1.7.9
|
105 |
-
*
|
106 |
-
* @param string The repository id (e.g. wpml)
|
107 |
-
* @return string The site key (or false)
|
108 |
-
*/
|
109 |
-
public static function get_site_key( $repository_id = 'wpml' ){
|
110 |
-
|
111 |
-
return WP_Installer()->get_site_key( $repository_id );
|
112 |
-
|
113 |
-
}
|
114 |
-
|
115 |
-
|
116 |
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WP_Installer_API{
|
4 |
+
|
5 |
+
public static function get_product_installer_link($repository_id, $package_id = false){
|
6 |
+
|
7 |
+
$menu_url = WP_Installer()->menu_url();
|
8 |
+
|
9 |
+
$url = $menu_url . '#' . $repository_id;
|
10 |
+
if($package_id){
|
11 |
+
$url .= '/' . $package_id;
|
12 |
+
}
|
13 |
+
|
14 |
+
return $url;
|
15 |
+
|
16 |
+
}
|
17 |
+
|
18 |
+
public static function get_product_price($repository_id, $package_id, $product_id, $incl_discount = false){
|
19 |
+
|
20 |
+
$price = WP_Installer()->get_product_price($repository_id, $package_id, $product_id, $incl_discount);
|
21 |
+
|
22 |
+
return $price;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Retrieve the preferred translation service.
|
27 |
+
*
|
28 |
+
* @since 1.6.5
|
29 |
+
*
|
30 |
+
* @param string The repository id (e.g. wpml)
|
31 |
+
* @return string The translation service id
|
32 |
+
*/
|
33 |
+
public static function get_preferred_ts($repository_id = 'wpml'){
|
34 |
+
|
35 |
+
if(isset(WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'])){
|
36 |
+
return WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'];
|
37 |
+
}
|
38 |
+
|
39 |
+
return false;
|
40 |
+
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Set the preferred translation service.
|
45 |
+
*
|
46 |
+
* @since 1.6.5
|
47 |
+
*
|
48 |
+
* @param string The translation service id
|
49 |
+
* @param string The repository id (e.g. wpml)
|
50 |
+
*/
|
51 |
+
public static function set_preferred_ts( $value, $repository_id = 'wpml' ){
|
52 |
+
|
53 |
+
if( isset( WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'] ) ){
|
54 |
+
|
55 |
+
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'] = $value;
|
56 |
+
|
57 |
+
WP_Installer()->save_settings();
|
58 |
+
|
59 |
+
}
|
60 |
+
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Retrieve the referring translation service (if any)
|
65 |
+
*
|
66 |
+
* @since 1.6.5
|
67 |
+
*
|
68 |
+
* @param string The repository id (e.g. wpml)
|
69 |
+
* @return string The translation service id or false
|
70 |
+
*/
|
71 |
+
public static function get_ts_referal($repository_id = 'wpml'){
|
72 |
+
|
73 |
+
if(isset(WP_Installer()->settings['repositories'][$repository_id]['ts_info']['referal'])){
|
74 |
+
return WP_Installer()->settings['repositories'][$repository_id]['ts_info']['referal'];
|
75 |
+
}
|
76 |
+
|
77 |
+
return false;
|
78 |
+
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Retrieve the translation services client id for a specific repository (if any)
|
83 |
+
*
|
84 |
+
* @since 1.7.9
|
85 |
+
*
|
86 |
+
* @param string The repository id (e.g. wpml)
|
87 |
+
* @return string The client id or false
|
88 |
+
*/
|
89 |
+
public static function get_ts_client_id( $repository_id = 'wpml' ){
|
90 |
+
|
91 |
+
if(isset(WP_Installer()->settings['repositories'][$repository_id]['ts_info']['client_id'])){
|
92 |
+
return WP_Installer()->settings['repositories'][$repository_id]['ts_info']['client_id'];
|
93 |
+
}
|
94 |
+
|
95 |
+
return false;
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Retrieve the site key corresponding to a repository.
|
101 |
+
* This is a wrapper of WP_Installer::get_site_key()
|
102 |
+
* @see WP_Installer::get_site_key()
|
103 |
+
*
|
104 |
+
* @since 1.7.9
|
105 |
+
*
|
106 |
+
* @param string The repository id (e.g. wpml)
|
107 |
+
* @return string The site key (or false)
|
108 |
+
*/
|
109 |
+
public static function get_site_key( $repository_id = 'wpml' ){
|
110 |
+
|
111 |
+
return WP_Installer()->get_site_key( $repository_id );
|
112 |
+
|
113 |
+
}
|
114 |
+
|
115 |
+
|
116 |
}
|
library/otgs/installer/includes/installer-upgrader-skins.php
CHANGED
@@ -1,37 +1,37 @@
|
|
1 |
-
<?php
|
2 |
-
class Installer_Upgrader_Skins extends WP_Upgrader_Skin{
|
3 |
-
|
4 |
-
function __construct($args = array()){
|
5 |
-
$defaults = array( 'url' => '', 'nonce' => '', 'title' => '', 'context' => false );
|
6 |
-
$this->options = wp_parse_args($args, $defaults);
|
7 |
-
}
|
8 |
-
|
9 |
-
function header(){
|
10 |
-
|
11 |
-
}
|
12 |
-
|
13 |
-
function footer(){
|
14 |
-
|
15 |
-
}
|
16 |
-
|
17 |
-
function error($error){
|
18 |
-
$this->installer_error = $error;
|
19 |
-
}
|
20 |
-
|
21 |
-
function add_strings(){
|
22 |
-
|
23 |
-
}
|
24 |
-
|
25 |
-
function feedback($string){
|
26 |
-
|
27 |
-
}
|
28 |
-
|
29 |
-
function before(){
|
30 |
-
|
31 |
-
}
|
32 |
-
|
33 |
-
function after(){
|
34 |
-
|
35 |
-
}
|
36 |
-
|
37 |
}
|
1 |
+
<?php
|
2 |
+
class Installer_Upgrader_Skins extends WP_Upgrader_Skin{
|
3 |
+
|
4 |
+
function __construct($args = array()){
|
5 |
+
$defaults = array( 'url' => '', 'nonce' => '', 'title' => '', 'context' => false );
|
6 |
+
$this->options = wp_parse_args($args, $defaults);
|
7 |
+
}
|
8 |
+
|
9 |
+
function header(){
|
10 |
+
|
11 |
+
}
|
12 |
+
|
13 |
+
function footer(){
|
14 |
+
|
15 |
+
}
|
16 |
+
|
17 |
+
function error($error){
|
18 |
+
$this->installer_error = $error;
|
19 |
+
}
|
20 |
+
|
21 |
+
function add_strings(){
|
22 |
+
|
23 |
+
}
|
24 |
+
|
25 |
+
function feedback($string){
|
26 |
+
|
27 |
+
}
|
28 |
+
|
29 |
+
function before(){
|
30 |
+
|
31 |
+
}
|
32 |
+
|
33 |
+
function after(){
|
34 |
+
|
35 |
+
}
|
36 |
+
|
37 |
}
|
library/otgs/installer/includes/installer.class.php
CHANGED
@@ -1,2579 +1,2672 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
final class WP_Installer{
|
4 |
-
protected static $_instance = null;
|
5 |
-
|
6 |
-
public $settings = array();
|
7 |
-
|
8 |
-
private $repositories = array();
|
9 |
-
|
10 |
-
protected $api_debug = '';
|
11 |
-
|
12 |
-
private $config = array();
|
13 |
-
|
14 |
-
protected $_plugins_renew_warnings = array();
|
15 |
-
|
16 |
-
protected $_gz_on = false;
|
17 |
-
|
18 |
-
private $admin_messages = array();
|
19 |
-
|
20 |
-
private $_using_icl = false;
|
21 |
-
private $_wpml_version = false;
|
22 |
-
|
23 |
-
private $package_source = array();
|
24 |
-
|
25 |
-
const SITE_KEY_VALIDATION_SOURCE_OTHER = 0;
|
26 |
-
const SITE_KEY_VALIDATION_SOURCE_DOWNLOAD_SPECIFIC = 1;
|
27 |
-
const SITE_KEY_VALIDATION_SOURCE_DOWNLOAD_REPORT = 2;
|
28 |
-
const SITE_KEY_VALIDATION_SOURCE_REGISTRATION = 3;
|
29 |
-
const SITE_KEY_VALIDATION_SOURCE_REVALIDATION = 4;
|
30 |
-
const SITE_KEY_VALIDATION_SOURCE_UPDATES_CHECK = 5;
|
31 |
-
|
32 |
-
public $dependencies;
|
33 |
-
|
34 |
-
public static function instance() {
|
35 |
-
|
36 |
-
if ( is_null( self::$_instance ) ) {
|
37 |
-
self::$_instance = new self();
|
38 |
-
}
|
39 |
-
|
40 |
-
return self::$_instance;
|
41 |
-
}
|
42 |
-
|
43 |
-
public function __construct(){
|
44 |
-
|
45 |
-
if(!is_admin() || !is_user_logged_in()) return; //Only for admin
|
46 |
-
|
47 |
-
$this->_gz_on = function_exists('gzuncompress') && function_exists('gzcompress');
|
48 |
-
$this->settings = $this->get_settings();
|
49 |
-
|
50 |
-
add_action('admin_notices', array($this, 'show_site_key_nags'));
|
51 |
-
|
52 |
-
add_action('admin_notices', array($this, 'show_admin_messages'));
|
53 |
-
|
54 |
-
add_action('admin_init', array($this, 'load_embedded_plugins'), 0);
|
55 |
-
|
56 |
-
add_action('admin_menu', array($this, 'menu_setup'));
|
57 |
-
add_action('network_admin_menu', array($this, 'menu_setup'));
|
58 |
-
|
59 |
-
if(defined('DOING_AJAX') && isset($_POST['action']) && $_POST['action'] == 'installer_download_plugin'){
|
60 |
-
add_filter( 'site_transient_update_plugins', array( $this, 'plugins_upgrade_check') );
|
61 |
-
}
|
62 |
-
add_filter('plugins_api', array( $this, 'custom_plugins_api_call'), 10, 3);
|
63 |
-
add_filter('pre_set_site_transient_update_plugins', array( $this, 'plugins_upgrade_check'));
|
64 |
-
|
65 |
-
// register repositories
|
66 |
-
$this->load_repositories_list();
|
67 |
-
|
68 |
-
if( empty($this->settings['last_repositories_update']) || time() - $this->settings['last_repositories_update'] > 86400
|
69 |
-
|| ( isset($_GET['force-check']) && $_GET['force-check'] == 1 ) ){
|
70 |
-
$this->refresh_repositories_data();
|
71 |
-
}
|
72 |
-
|
73 |
-
// default config
|
74 |
-
$this->config['plugins_install_tab'] = false;
|
75 |
-
|
76 |
-
add_action('init', array($this, 'init'));
|
77 |
-
|
78 |
-
//add_filter('wp_installer_buy_url', array($this, 'append_parameters_to_buy_url'));
|
79 |
-
|
80 |
-
add_action('init', array($this,'load_locale'));
|
81 |
-
|
82 |
-
}
|
83 |
-
|
84 |
-
public function get_repositories() {
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
}
|
89 |
-
|
90 |
-
public function set_config($key, $value){
|
91 |
-
|
92 |
-
$this->config[$key] = $value;
|
93 |
-
|
94 |
-
}
|
95 |
-
|
96 |
-
public function init(){
|
97 |
-
global $pagenow;
|
98 |
-
|
99 |
-
$this->dependencies = new Installer_Dependencies;
|
100 |
-
|
101 |
-
if(empty($this->settings['_pre_1_0_clean_up'])) {
|
102 |
-
$this->_pre_1_0_clean_up();
|
103 |
-
}
|
104 |
-
|
105 |
-
$this->settings = $this->_old_products_format_backwards_compatibility($this->settings);
|
106 |
-
|
107 |
-
if ( !function_exists( 'get_plugins' ) ) {
|
108 |
-
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
109 |
-
}
|
110 |
-
|
111 |
-
$this->_using_icl = function_exists('wpml_site_uses_icl') && wpml_site_uses_icl();
|
112 |
-
$this->_wpml_version = defined('ICL_SITEPRESS_VERSION') ? ICL_SITEPRESS_VERSION : '';
|
113 |
-
|
114 |
-
wp_enqueue_script('installer-admin', $this->res_url() . '/res/js/admin.js', array('jquery'), $this->version());
|
115 |
-
wp_enqueue_style('installer-admin', $this->res_url() . '/res/css/admin.css', array(), $this->version());
|
116 |
-
|
117 |
-
$translation_array = array(
|
118 |
-
'installing' => __( 'Installing %s', 'installer' ),
|
119 |
-
'updating' => __( 'Updating %s', 'installer' ),
|
120 |
-
'activating' => __( 'Activating %s', 'installer' )
|
121 |
-
);
|
122 |
-
|
123 |
-
wp_localize_script( 'installer-admin', 'installer_strings', $translation_array );
|
124 |
-
|
125 |
-
if($pagenow == 'plugins.php'){
|
126 |
-
add_action('admin_notices', array($this, 'setup_plugins_page_notices'));
|
127 |
-
add_action('admin_notices', array($this, 'setup_plugins_renew_warnings'), 10);
|
128 |
-
add_action('admin_notices', array($this, 'queue_plugins_renew_warnings'), 20);
|
129 |
-
|
130 |
-
add_action('admin_init', array($this, 'setup_plugins_action_links'));
|
131 |
-
|
132 |
-
}
|
133 |
-
|
134 |
-
if($this->is_repositories_page()){
|
135 |
-
add_action('admin_init', array($this, 'validate_repository_subscription'));
|
136 |
-
}
|
137 |
-
|
138 |
-
if(defined('DOING_AJAX')){
|
139 |
-
add_action('wp_ajax_save_site_key', array($this, 'save_site_key'));
|
140 |
-
add_action('wp_ajax_remove_site_key', array($this, '
|
141 |
-
add_action('wp_ajax_update_site_key', array($this, 'update_site_key'));
|
142 |
-
|
143 |
-
add_action('wp_ajax_installer_download_plugin', array($this, 'download_plugin_ajax_handler'));
|
144 |
-
add_action('wp_ajax_installer_activate_plugin', array($this, 'activate_plugin'));
|
145 |
-
|
146 |
-
add_action('wp_ajax_installer_dismiss_nag', array($this, 'dismiss_nag'));
|
147 |
-
}
|
148 |
-
|
149 |
-
if($pagenow == 'update.php'){
|
150 |
-
if(isset($_GET['action']) && $_GET['action'] == 'update-selected'){
|
151 |
-
add_action('admin_head', array($this, 'plugin_upgrade_custom_errors')); //iframe/bulk
|
152 |
-
}else{
|
153 |
-
add_action('all_admin_notices', array($this, 'plugin_upgrade_custom_errors')); //regular/singular
|
154 |
-
}
|
155 |
-
}
|
156 |
-
|
157 |
-
// WP 4.2
|
158 |
-
if(defined('DOING_AJAX')){
|
159 |
-
add_action('wp_ajax_update-plugin', array($this, 'plugin_upgrade_custom_errors'), 0); // high priority, before WP
|
160 |
-
}
|
161 |
-
|
162 |
-
//Include theme support
|
163 |
-
include_once $this->plugin_path() . '/includes/class-installer-theme.php';
|
164 |
-
|
165 |
-
// Extra information about the source of Installer
|
166 |
-
$package_source_file = $this->plugin_path() . '/installer-source.json';
|
167 |
-
if( file_exists( $package_source_file ) ){
|
168 |
-
$this->package_source = json_decode( file_get_contents( $package_source_file ) );
|
169 |
-
}
|
170 |
-
}
|
171 |
-
|
172 |
-
protected function log($message){
|
173 |
-
if( defined('WPML_INSTALLER_LOGGING') && WPML_INSTALLER_LOGGING ){
|
174 |
-
if($fh = @fopen( $this->plugin_path() . '/installer.log', 'a' )){
|
175 |
-
fwrite($fh, current_time( 'mysql' ) . "\t" . $message . "\n");
|
176 |
-
}
|
177 |
-
}
|
178 |
-
}
|
179 |
-
|
180 |
-
public function register_admin_message($text, $type = 'updated'){
|
181 |
-
$this->admin_messages[] = array('text' => $text, 'type' => $type);
|
182 |
-
}
|
183 |
-
|
184 |
-
public function show_admin_messages(){
|
185 |
-
if(!empty($this->admin_messages)){
|
186 |
-
$types = array( 'error', 'updated', 'notice' );
|
187 |
-
foreach($this->admin_messages as $message){
|
188 |
-
$class = in_array( $message['type'], $types ) ? $message['type'] : 'updated';
|
189 |
-
?>
|
190 |
-
<div class="<?php echo $class ?>">
|
191 |
-
<p>
|
192 |
-
<?php echo $message['text'] ?>
|
193 |
-
</p>
|
194 |
-
</div>
|
195 |
-
<?php
|
196 |
-
}
|
197 |
-
}
|
198 |
-
}
|
199 |
-
|
200 |
-
public function load_locale(){
|
201 |
-
$locale = get_locale();
|
202 |
-
$locale = apply_filters( 'plugin_locale', $locale, 'installer' );
|
203 |
-
$mo_file = $this->plugin_path() . '/locale/installer-' . $locale . '.mo';
|
204 |
-
if(file_exists($mo_file)){
|
205 |
-
load_textdomain( 'installer', $mo_file );
|
206 |
-
}
|
207 |
-
}
|
208 |
-
|
209 |
-
public function load_embedded_plugins(){
|
210 |
-
if(file_exists($this->plugin_path() . '/embedded-plugins' )) {
|
211 |
-
include_once $this->plugin_path() . '/embedded-plugins/embedded-plugins.class.php';
|
212 |
-
$this->installer_embedded_plugins = new Installer_Embedded_Plugins();
|
213 |
-
}
|
214 |
-
}
|
215 |
-
|
216 |
-
public function menu_setup(){
|
217 |
-
global $pagenow;
|
218 |
-
|
219 |
-
if(is_multisite() && !is_network_admin()){
|
220 |
-
$this->menu_multisite_redirect();
|
221 |
-
add_options_page(__('Installer', 'installer'), __('Installer', 'installer'), 'manage_options', 'installer', array($this, 'show_products')) ;
|
222 |
-
}else{
|
223 |
-
if($this->config['plugins_install_tab'] && is_admin() && $pagenow == 'plugin-install.php'){
|
224 |
-
// Default GUI, under Plugins -> Install
|
225 |
-
add_filter('install_plugins_tabs', array($this, 'add_install_plugins_tab'));
|
226 |
-
add_action('install_plugins_commercial', array($this, 'show_products'));
|
227 |
-
}
|
228 |
-
}
|
229 |
-
|
230 |
-
}
|
231 |
-
|
232 |
-
public function menu_url(){
|
233 |
-
if(is_multisite()){
|
234 |
-
if(is_network_admin()){
|
235 |
-
$url = network_admin_url('plugin-install.php?tab=commercial');
|
236 |
-
}else{
|
237 |
-
$url = admin_url('options-general.php?page=installer');
|
238 |
-
}
|
239 |
-
}else{
|
240 |
-
$url = admin_url('plugin-install.php?tab=commercial');
|
241 |
-
}
|
242 |
-
return $url;
|
243 |
-
}
|
244 |
-
|
245 |
-
private function menu_multisite_redirect(){
|
246 |
-
global $pagenow;
|
247 |
-
|
248 |
-
if($pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial'){
|
249 |
-
wp_redirect($this->menu_url());
|
250 |
-
exit;
|
251 |
-
}
|
252 |
-
|
253 |
-
}
|
254 |
-
|
255 |
-
private function _pre_1_0_clean_up(){
|
256 |
-
global $wpdb;
|
257 |
-
|
258 |
-
if(!defined('WPRC_VERSION')){
|
259 |
-
$old_tables = array(
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
);
|
266 |
-
|
267 |
-
foreach($old_tables as $table){
|
268 |
-
$wpdb->query(sprintf("DROP TABLE IF EXISTS %s", $table));
|
269 |
-
}
|
270 |
-
|
271 |
-
}
|
272 |
-
|
273 |
-
$this->settings['_pre_1_0_clean_up'] = true;
|
274 |
-
$this->save_settings();
|
275 |
-
}
|
276 |
-
|
277 |
-
public function setup_plugins_action_links(){
|
278 |
-
|
279 |
-
$plugins = get_plugins();
|
280 |
-
|
281 |
-
$repositories_plugins = array();
|
282 |
-
|
283 |
-
if( !empty($this->settings['repositories']) ) {
|
284 |
-
|
285 |
-
foreach ( $this->settings['repositories'] as $repository_id => $repository ) {
|
286 |
-
|
287 |
-
foreach ( $repository['data']['packages'] as $package ) {
|
288 |
-
|
289 |
-
foreach ( $package['products'] as $product ) {
|
290 |
-
|
291 |
-
foreach ( $product['plugins'] as $plugin_slug ) {
|
292 |
-
|
293 |
-
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
294 |
-
|
295 |
-
if ( !isset($repositories_plugins[$repository_id][$download['slug']]) ) {
|
296 |
-
$repositories_plugins[$repository_id][$download['slug']] = array(
|
297 |
-
'name' => $download['name'],
|
298 |
-
'registered' => $this->plugin_is_registered( $repository_id, $download['slug'] ) ? 1 : 0
|
299 |
-
);
|
300 |
-
}
|
301 |
-
|
302 |
-
}
|
303 |
-
|
304 |
-
}
|
305 |
-
|
306 |
-
}
|
307 |
-
|
308 |
-
foreach ( $plugins as $plugin_id => $plugin ) {
|
309 |
-
|
310 |
-
$wp_plugin_slug = dirname( $plugin_id );
|
311 |
-
if ( empty($wp_plugin_slug) ) {
|
312 |
-
$wp_plugin_slug = basename( $plugin_id, '.php' );
|
313 |
-
}
|
314 |
-
|
315 |
-
foreach ( $repositories_plugins as $repository_id => $r_plugins ) {
|
316 |
-
|
317 |
-
foreach ( $r_plugins as $slug => $r_plugin ) {
|
318 |
-
|
319 |
-
if ( $wp_plugin_slug == $slug || $r_plugin['name'] == $plugin['Name'] || $r_plugin['name'] == $plugin['Title'] ) { //match order: slug, name, title
|
320 |
-
|
321 |
-
if ( $r_plugin['registered'] ) {
|
322 |
-
add_filter( 'plugin_action_links_' . $plugin_id, array($this, 'plugins_action_links_registered') );
|
323 |
-
} else {
|
324 |
-
add_filter( 'plugin_action_links_' . $plugin_id, array($this, 'plugins_action_links_not_registered') );
|
325 |
-
}
|
326 |
-
|
327 |
-
}
|
328 |
-
|
329 |
-
}
|
330 |
-
|
331 |
-
}
|
332 |
-
|
333 |
-
|
334 |
-
}
|
335 |
-
|
336 |
-
}
|
337 |
-
}
|
338 |
-
|
339 |
-
}
|
340 |
-
|
341 |
-
public function plugins_action_links_registered($links){
|
342 |
-
$links[] = '<a href="' . $this->menu_url() . '">' . __('Registered', 'installer') . '</a>';
|
343 |
-
return $links;
|
344 |
-
}
|
345 |
-
|
346 |
-
public function plugins_action_links_not_registered($links){
|
347 |
-
$links[] = '<a href="' . $this->menu_url() . '">' . __('Register', 'installer') . '</a>';
|
348 |
-
return $links;
|
349 |
-
}
|
350 |
-
|
351 |
-
public function plugin_is_registered($repository_id, $slug){
|
352 |
-
|
353 |
-
$registered = false;
|
354 |
-
|
355 |
-
if( $this->repository_has_valid_subscription($repository_id) ){
|
356 |
-
|
357 |
-
$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
358 |
-
$r_plugins = array();
|
359 |
-
|
360 |
-
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
|
361 |
-
|
362 |
-
foreach($package['products'] as $product){
|
363 |
-
|
364 |
-
if( $product['subscription_type'] == $subscription_type || $this->have_superior_subscription($subscription_type, $product) ) {
|
365 |
-
|
366 |
-
foreach ($product['plugins'] as $plugin_slug) {
|
367 |
-
|
368 |
-
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
369 |
-
|
370 |
-
if (!isset($rep_plugins[$download['slug']])) {
|
371 |
-
$r_plugins[$download['slug']] = $download['slug'];
|
372 |
-
}
|
373 |
-
|
374 |
-
}
|
375 |
-
|
376 |
-
}
|
377 |
-
|
378 |
-
}
|
379 |
-
|
380 |
-
}
|
381 |
-
|
382 |
-
$registered = isset($r_plugins[$slug]);
|
383 |
-
|
384 |
-
}
|
385 |
-
|
386 |
-
|
387 |
-
return $registered;
|
388 |
-
|
389 |
-
}
|
390 |
-
|
391 |
-
public function version(){
|
392 |
-
return WP_INSTALLER_VERSION;
|
393 |
-
}
|
394 |
-
|
395 |
-
public function plugin_path() {
|
396 |
-
return untrailingslashit( plugin_dir_path( dirname(__FILE__) ) );
|
397 |
-
}
|
398 |
-
|
399 |
-
public function plugin_url() {
|
400 |
-
if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
|
401 |
-
$url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
|
402 |
-
}else{
|
403 |
-
$url = untrailingslashit( plugins_url( '/', dirname(__FILE__) ) );
|
404 |
-
}
|
405 |
-
|
406 |
-
return $url;
|
407 |
-
}
|
408 |
-
|
409 |
-
public function is_repositories_page(){
|
410 |
-
global $pagenow;
|
411 |
-
|
412 |
-
return $pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial';
|
413 |
-
}
|
414 |
-
|
415 |
-
public function res_url(){
|
416 |
-
if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
|
417 |
-
$url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
|
418 |
-
}else{
|
419 |
-
$url = $this->plugin_url();
|
420 |
-
}
|
421 |
-
return $url;
|
422 |
-
}
|
423 |
-
|
424 |
-
public function save_settings(){
|
425 |
-
|
426 |
-
$_settings = serialize($this->settings);
|
427 |
-
if($this->_gz_on){
|
428 |
-
$_settings = gzcompress($_settings);
|
429 |
-
}
|
430 |
-
$_settings = base64_encode($_settings);
|
431 |
-
|
432 |
-
update_option( 'wp_installer_settings', $_settings );
|
433 |
-
|
434 |
-
if( is_multisite() && is_main_site() && isset($this->settings['repositories']) ){
|
435 |
-
$network_settings = array();
|
436 |
-
|
437 |
-
foreach( $this->settings['repositories'] as $rep_id => $repository ){
|
438 |
-
if( isset($repository['subscription']) )
|
439 |
-
$network_settings[$rep_id] = $repository['subscription'];
|
440 |
-
}
|
441 |
-
|
442 |
-
update_site_option( 'wp_installer_network', $network_settings );
|
443 |
-
|
444 |
-
|
445 |
-
}
|
446 |
-
|
447 |
-
}
|
448 |
-
|
449 |
-
public function get_settings($refresh = false){
|
450 |
-
|
451 |
-
if($refresh || empty($this->settings)){
|
452 |
-
|
453 |
-
$_settings = get_option('wp_installer_settings');
|
454 |
-
|
455 |
-
|
456 |
-
if (is_array($_settings) || empty($_settings)) { //backward compatibility 1.1
|
457 |
-
$this->settings = $_settings;
|
458 |
-
|
459 |
-
} else {
|
460 |
-
$_settings = base64_decode($_settings);
|
461 |
-
if ($this->_gz_on) {
|
462 |
-
$_settings = gzuncompress($_settings);
|
463 |
-
}
|
464 |
-
$this->settings = unserialize($_settings);
|
465 |
-
}
|
466 |
-
|
467 |
-
if (is_multisite() && isset($this->settings['repositories'])) {
|
468 |
-
$network_settings = maybe_unserialize(get_site_option('wp_installer_network'));
|
469 |
-
if ($network_settings) {
|
470 |
-
foreach ($this->settings['repositories'] as $rep_id => $repository) {
|
471 |
-
if (isset($network_settings[$rep_id])) {
|
472 |
-
$this->settings['repositories'][$rep_id]['subscription'] = $network_settings[$rep_id];
|
473 |
-
}
|
474 |
-
}
|
475 |
-
}
|
476 |
-
}
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
return $this->settings;
|
487 |
-
}
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
$
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
}
|
678 |
-
|
679 |
-
}
|
680 |
-
|
681 |
-
public function
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
$
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
$
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
}
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
$
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
$
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
//
|
924 |
-
if(
|
925 |
-
|
926 |
-
}
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
$
|
990 |
-
$
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
if($
|
1009 |
-
$
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
$
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
$
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
$
|
1088 |
-
|
1089 |
-
$
|
1090 |
-
}
|
1091 |
-
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
1135 |
-
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
-
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
-
|
1163 |
-
|
1164 |
-
|
1165 |
-
|
1166 |
-
|
1167 |
-
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
}
|
1172 |
-
|
1173 |
-
}
|
1174 |
-
|
1175 |
-
public function
|
1176 |
-
|
1177 |
-
$
|
1178 |
-
|
1179 |
-
|
1180 |
-
|
1181 |
-
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
1186 |
-
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
$
|
1226 |
-
|
1227 |
-
|
1228 |
-
|
1229 |
-
|
1230 |
-
|
1231 |
-
|
1232 |
-
|
1233 |
-
|
1234 |
-
|
1235 |
-
|
1236 |
-
|
1237 |
-
|
1238 |
-
|
1239 |
-
|
1240 |
-
|
1241 |
-
|
1242 |
-
|
1243 |
-
|
1244 |
-
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
$
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
1298 |
-
if(!
|
1299 |
-
$
|
1300 |
-
|
1301 |
-
|
1302 |
-
|
1303 |
-
|
1304 |
-
|
1305 |
-
|
1306 |
-
|
1307 |
-
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
|
1313 |
-
|
1314 |
-
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
$
|
1336 |
-
|
1337 |
-
|
1338 |
-
|
1339 |
-
|
1340 |
-
|
1341 |
-
|
1342 |
-
|
1343 |
-
|
1344 |
-
|
1345 |
-
|
1346 |
-
|
1347 |
-
|
1348 |
-
|
1349 |
-
|
1350 |
-
|
1351 |
-
|
1352 |
-
|
1353 |
-
|
1354 |
-
|
1355 |
-
|
1356 |
-
|
1357 |
-
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
|
1362 |
-
|
1363 |
-
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
1368 |
-
|
1369 |
-
|
1370 |
-
|
1371 |
-
|
1372 |
-
|
1373 |
-
|
1374 |
-
|
1375 |
-
|
1376 |
-
|
1377 |
-
|
1378 |
-
|
1379 |
-
|
1380 |
-
|
1381 |
-
|
1382 |
-
|
1383 |
-
|
1384 |
-
|
1385 |
-
|
1386 |
-
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
1392 |
-
|
1393 |
-
|
1394 |
-
|
1395 |
-
|
1396 |
-
|
1397 |
-
|
1398 |
-
|
1399 |
-
|
1400 |
-
|
1401 |
-
|
1402 |
-
|
1403 |
-
|
1404 |
-
|
1405 |
-
|
1406 |
-
|
1407 |
-
|
1408 |
-
|
1409 |
-
|
1410 |
-
|
1411 |
-
|
1412 |
-
|
1413 |
-
|
1414 |
-
|
1415 |
-
|
1416 |
-
|
1417 |
-
|
1418 |
-
|
1419 |
-
|
1420 |
-
|
1421 |
-
|
1422 |
-
|
1423 |
-
|
1424 |
-
|
1425 |
-
|
1426 |
-
|
1427 |
-
|
1428 |
-
|
1429 |
-
|
1430 |
-
|
1431 |
-
|
1432 |
-
|
1433 |
-
|
1434 |
-
|
1435 |
-
|
1436 |
-
|
1437 |
-
|
1438 |
-
|
1439 |
-
|
1440 |
-
|
1441 |
-
|
1442 |
-
|
1443 |
-
|
1444 |
-
|
1445 |
-
|
1446 |
-
|
1447 |
-
|
1448 |
-
|
1449 |
-
|
1450 |
-
|
1451 |
-
|
1452 |
-
|
1453 |
-
|
1454 |
-
|
1455 |
-
|
1456 |
-
|
1457 |
-
|
1458 |
-
|
1459 |
-
|
1460 |
-
|
1461 |
-
|
1462 |
-
|
1463 |
-
|
1464 |
-
|
1465 |
-
|
1466 |
-
|
1467 |
-
|
1468 |
-
|
1469 |
-
|
1470 |
-
|
1471 |
-
|
1472 |
-
|
1473 |
-
|
1474 |
-
|
1475 |
-
|
1476 |
-
|
1477 |
-
|
1478 |
-
|
1479 |
-
|
1480 |
-
|
1481 |
-
|
1482 |
-
|
1483 |
-
|
1484 |
-
|
1485 |
-
|
1486 |
-
|
1487 |
-
|
1488 |
-
|
1489 |
-
|
1490 |
-
|
1491 |
-
|
1492 |
-
|
1493 |
-
|
1494 |
-
|
1495 |
-
|
1496 |
-
|
1497 |
-
|
1498 |
-
|
1499 |
-
|
1500 |
-
|
1501 |
-
|
1502 |
-
|
1503 |
-
|
1504 |
-
|
1505 |
-
|
1506 |
-
|
1507 |
-
|
1508 |
-
|
1509 |
-
|
1510 |
-
|
1511 |
-
|
1512 |
-
|
1513 |
-
|
1514 |
-
|
1515 |
-
|
1516 |
-
|
1517 |
-
|
1518 |
-
|
1519 |
-
|
1520 |
-
|
1521 |
-
|
1522 |
-
|
1523 |
-
|
1524 |
-
|
1525 |
-
|
1526 |
-
|
1527 |
-
|
1528 |
-
|
1529 |
-
|
1530 |
-
|
1531 |
-
|
1532 |
-
|
1533 |
-
|
1534 |
-
|
1535 |
-
|
1536 |
-
|
1537 |
-
|
1538 |
-
|
1539 |
-
|
1540 |
-
|
1541 |
-
|
1542 |
-
|
1543 |
-
|
1544 |
-
|
1545 |
-
|
1546 |
-
|
1547 |
-
|
1548 |
-
|
1549 |
-
|
1550 |
-
|
1551 |
-
|
1552 |
-
|
1553 |
-
|
1554 |
-
|
1555 |
-
|
1556 |
-
|
1557 |
-
|
1558 |
-
|
1559 |
-
|
1560 |
-
|
1561 |
-
|
1562 |
-
|
1563 |
-
|
1564 |
-
|
1565 |
-
|
1566 |
-
|
1567 |
-
|
1568 |
-
|
1569 |
-
|
1570 |
-
|
1571 |
-
|
1572 |
-
|
1573 |
-
|
1574 |
-
|
1575 |
-
|
1576 |
-
|
1577 |
-
|
1578 |
-
|
1579 |
-
|
1580 |
-
|
1581 |
-
|
1582 |
-
|
1583 |
-
|
1584 |
-
|
1585 |
-
|
1586 |
-
|
1587 |
-
|
1588 |
-
|
1589 |
-
|
1590 |
-
|
1591 |
-
|
1592 |
-
|
1593 |
-
|
1594 |
-
|
1595 |
-
|
1596 |
-
|
1597 |
-
|
1598 |
-
|
1599 |
-
|
1600 |
-
|
1601 |
-
|
1602 |
-
|
1603 |
-
|
1604 |
-
|
1605 |
-
|
1606 |
-
|
1607 |
-
|
1608 |
-
|
1609 |
-
|
1610 |
-
|
1611 |
-
|
1612 |
-
|
1613 |
-
|
1614 |
-
|
1615 |
-
|
1616 |
-
|
1617 |
-
|
1618 |
-
|
1619 |
-
|
1620 |
-
|
1621 |
-
|
1622 |
-
|
1623 |
-
|
1624 |
-
|
1625 |
-
|
1626 |
-
|
1627 |
-
|
1628 |
-
|
1629 |
-
|
1630 |
-
|
1631 |
-
|
1632 |
-
|
1633 |
-
|
1634 |
-
|
1635 |
-
|
1636 |
-
|
1637 |
-
|
1638 |
-
|
1639 |
-
|
1640 |
-
|
1641 |
-
|
1642 |
-
|
1643 |
-
|
1644 |
-
|
1645 |
-
|
1646 |
-
|
1647 |
-
|
1648 |
-
|
1649 |
-
|
1650 |
-
|
1651 |
-
|
1652 |
-
|
1653 |
-
|
1654 |
-
|
1655 |
-
|
1656 |
-
|
1657 |
-
|
1658 |
-
|
1659 |
-
|
1660 |
-
|
1661 |
-
|
1662 |
-
|
1663 |
-
|
1664 |
-
|
1665 |
-
|
1666 |
-
if(
|
1667 |
-
$
|
1668 |
-
|
1669 |
-
|
1670 |
-
|
1671 |
-
|
1672 |
-
|
1673 |
-
|
1674 |
-
|
1675 |
-
|
1676 |
-
|
1677 |
-
|
1678 |
-
|
1679 |
-
|
1680 |
-
|
1681 |
-
|
1682 |
-
|
1683 |
-
|
1684 |
-
|
1685 |
-
|
1686 |
-
|
1687 |
-
|
1688 |
-
|
1689 |
-
|
1690 |
-
|
1691 |
-
|
1692 |
-
|
1693 |
-
|
1694 |
-
|
1695 |
-
|
1696 |
-
|
1697 |
-
|
1698 |
-
|
1699 |
-
|
1700 |
-
|
1701 |
-
|
1702 |
-
|
1703 |
-
|
1704 |
-
|
1705 |
-
|
1706 |
-
|
1707 |
-
|
1708 |
-
|
1709 |
-
|
1710 |
-
|
1711 |
-
|
1712 |
-
|
1713 |
-
|
1714 |
-
|
1715 |
-
|
1716 |
-
|
1717 |
-
|
1718 |
-
|
1719 |
-
|
1720 |
-
|
1721 |
-
|
1722 |
-
|
1723 |
-
|
1724 |
-
|
1725 |
-
|
1726 |
-
|
1727 |
-
|
1728 |
-
|
1729 |
-
|
1730 |
-
|
1731 |
-
|
1732 |
-
|
1733 |
-
|
1734 |
-
|
1735 |
-
|
1736 |
-
|
1737 |
-
|
1738 |
-
|
1739 |
-
|
1740 |
-
|
1741 |
-
|
1742 |
-
$
|
1743 |
-
|
1744 |
-
|
1745 |
-
|
1746 |
-
|
1747 |
-
|
1748 |
-
|
1749 |
-
|
1750 |
-
|
1751 |
-
|
1752 |
-
|
1753 |
-
|
1754 |
-
|
1755 |
-
|
1756 |
-
|
1757 |
-
|
1758 |
-
|
1759 |
-
|
1760 |
-
|
1761 |
-
|
1762 |
-
|
1763 |
-
|
1764 |
-
|
1765 |
-
|
1766 |
-
|
1767 |
-
|
1768 |
-
|
1769 |
-
|
1770 |
-
|
1771 |
-
|
1772 |
-
|
1773 |
-
|
1774 |
-
|
1775 |
-
|
1776 |
-
|
1777 |
-
|
1778 |
-
|
1779 |
-
|
1780 |
-
|
1781 |
-
|
1782 |
-
|
1783 |
-
|
1784 |
-
|
1785 |
-
|
1786 |
-
|
1787 |
-
|
1788 |
-
|
1789 |
-
|
1790 |
-
|
1791 |
-
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
1795 |
-
|
1796 |
-
|
1797 |
-
|
1798 |
-
|
1799 |
-
|
1800 |
-
|
1801 |
-
|
1802 |
-
|
1803 |
-
|
1804 |
-
|
1805 |
-
|
1806 |
-
|
1807 |
-
|
1808 |
-
|
1809 |
-
|
1810 |
-
|
1811 |
-
|
1812 |
-
|
1813 |
-
|
1814 |
-
|
1815 |
-
|
1816 |
-
|
1817 |
-
|
1818 |
-
|
1819 |
-
|
1820 |
-
|
1821 |
-
|
1822 |
-
|
1823 |
-
|
1824 |
-
|
1825 |
-
|
1826 |
-
|
1827 |
-
|
1828 |
-
|
1829 |
-
|
1830 |
-
|
1831 |
-
|
1832 |
-
|
1833 |
-
|
1834 |
-
|
1835 |
-
|
1836 |
-
|
1837 |
-
|
1838 |
-
|
1839 |
-
|
1840 |
-
|
1841 |
-
|
1842 |
-
|
1843 |
-
|
1844 |
-
|
1845 |
-
|
1846 |
-
|
1847 |
-
|
1848 |
-
|
1849 |
-
|
1850 |
-
|
1851 |
-
|
1852 |
-
|
1853 |
-
|
1854 |
-
|
1855 |
-
|
1856 |
-
|
1857 |
-
|
1858 |
-
|
1859 |
-
|
1860 |
-
|
1861 |
-
|
1862 |
-
|
1863 |
-
|
1864 |
-
|
1865 |
-
|
1866 |
-
|
1867 |
-
|
1868 |
-
|
1869 |
-
|
1870 |
-
|
1871 |
-
|
1872 |
-
|
1873 |
-
|
1874 |
-
|
1875 |
-
|
1876 |
-
|
1877 |
-
|
1878 |
-
|
1879 |
-
|
1880 |
-
|
1881 |
-
|
1882 |
-
|
1883 |
-
|
1884 |
-
|
1885 |
-
|
1886 |
-
|
1887 |
-
|
1888 |
-
|
1889 |
-
|
1890 |
-
|
1891 |
-
|
1892 |
-
|
1893 |
-
|
1894 |
-
|
1895 |
-
|
1896 |
-
|
1897 |
-
|
1898 |
-
}
|
1899 |
-
|
1900 |
-
|
1901 |
-
|
1902 |
-
|
1903 |
-
|
1904 |
-
$
|
1905 |
-
|
1906 |
-
|
1907 |
-
|
1908 |
-
|
1909 |
-
|
1910 |
-
|
1911 |
-
|
1912 |
-
|
1913 |
-
|
1914 |
-
|
1915 |
-
|
1916 |
-
|
1917 |
-
|
1918 |
-
|
1919 |
-
|
1920 |
-
|
1921 |
-
|
1922 |
-
|
1923 |
-
|
1924 |
-
|
1925 |
-
|
1926 |
-
|
1927 |
-
|
1928 |
-
|
1929 |
-
|
1930 |
-
|
1931 |
-
|
1932 |
-
|
1933 |
-
|
1934 |
-
|
1935 |
-
|
1936 |
-
|
1937 |
-
|
1938 |
-
|
1939 |
-
|
1940 |
-
|
1941 |
-
|
1942 |
-
|
1943 |
-
|
1944 |
-
|
1945 |
-
|
1946 |
-
|
1947 |
-
|
1948 |
-
|
1949 |
-
|
1950 |
-
|
1951 |
-
|
1952 |
-
|
1953 |
-
|
1954 |
-
|
1955 |
-
|
1956 |
-
|
1957 |
-
|
1958 |
-
|
1959 |
-
|
1960 |
-
|
1961 |
-
|
1962 |
-
|
1963 |
-
|
1964 |
-
|
1965 |
-
|
1966 |
-
|
1967 |
-
|
1968 |
-
|
1969 |
-
|
1970 |
-
|
1971 |
-
|
1972 |
-
|
1973 |
-
|
1974 |
-
|
1975 |
-
|
1976 |
-
}
|
1977 |
-
|
1978 |
-
|
1979 |
-
|
1980 |
-
|
1981 |
-
|
1982 |
-
|
1983 |
-
|
1984 |
-
|
1985 |
-
|
1986 |
-
|
1987 |
-
|
1988 |
-
$
|
1989 |
-
|
1990 |
-
|
1991 |
-
|
1992 |
-
|
1993 |
-
|
1994 |
-
|
1995 |
-
|
1996 |
-
|
1997 |
-
|
1998 |
-
|
1999 |
-
|
2000 |
-
|
2001 |
-
|
2002 |
-
|
2003 |
-
|
2004 |
-
|
2005 |
-
|
2006 |
-
|
2007 |
-
|
2008 |
-
|
2009 |
-
|
2010 |
-
|
2011 |
-
|
2012 |
-
|
2013 |
-
|
2014 |
-
|
2015 |
-
|
2016 |
-
|
2017 |
-
|
2018 |
-
|
2019 |
-
|
2020 |
-
|
2021 |
-
|
2022 |
-
|
2023 |
-
|
2024 |
-
|
2025 |
-
|
2026 |
-
|
2027 |
-
|
2028 |
-
|
2029 |
-
|
2030 |
-
|
2031 |
-
|
2032 |
-
|
2033 |
-
$
|
2034 |
-
|
2035 |
-
|
2036 |
-
|
2037 |
-
|
2038 |
-
|
2039 |
-
|
2040 |
-
|
2041 |
-
|
2042 |
-
|
2043 |
-
|
2044 |
-
|
2045 |
-
|
2046 |
-
|
2047 |
-
|
2048 |
-
|
2049 |
-
|
2050 |
-
|
2051 |
-
|
2052 |
-
|
2053 |
-
|
2054 |
-
|
2055 |
-
|
2056 |
-
|
2057 |
-
|
2058 |
-
|
2059 |
-
|
2060 |
-
|
2061 |
-
|
2062 |
-
|
2063 |
-
|
2064 |
-
|
2065 |
-
|
2066 |
-
|
2067 |
-
|
2068 |
-
|
2069 |
-
|
2070 |
-
|
2071 |
-
|
2072 |
-
|
2073 |
-
|
2074 |
-
|
2075 |
-
|
2076 |
-
|
2077 |
-
|
2078 |
-
|
2079 |
-
|
2080 |
-
|
2081 |
-
|
2082 |
-
|
2083 |
-
|
2084 |
-
|
2085 |
-
|
2086 |
-
|
2087 |
-
|
2088 |
-
|
2089 |
-
|
2090 |
-
|
2091 |
-
|
2092 |
-
|
2093 |
-
|
2094 |
-
|
2095 |
-
|
2096 |
-
|
2097 |
-
|
2098 |
-
|
2099 |
-
|
2100 |
-
|
2101 |
-
|
2102 |
-
|
2103 |
-
|
2104 |
-
|
2105 |
-
|
2106 |
-
|
2107 |
-
|
2108 |
-
|
2109 |
-
|
2110 |
-
|
2111 |
-
|
2112 |
-
|
2113 |
-
|
2114 |
-
|
2115 |
-
|
2116 |
-
|
2117 |
-
|
2118 |
-
|
2119 |
-
|
2120 |
-
|
2121 |
-
|
2122 |
-
|
2123 |
-
|
2124 |
-
|
2125 |
-
|
2126 |
-
|
2127 |
-
|
2128 |
-
|
2129 |
-
|
2130 |
-
|
2131 |
-
|
2132 |
-
|
2133 |
-
|
2134 |
-
|
2135 |
-
|
2136 |
-
|
2137 |
-
|
2138 |
-
|
2139 |
-
|
2140 |
-
|
2141 |
-
|
2142 |
-
|
2143 |
-
|
2144 |
-
|
2145 |
-
|
2146 |
-
|
2147 |
-
|
2148 |
-
|
2149 |
-
|
2150 |
-
|
2151 |
-
|
2152 |
-
|
2153 |
-
|
2154 |
-
|
2155 |
-
|
2156 |
-
|
2157 |
-
|
2158 |
-
|
2159 |
-
|
2160 |
-
|
2161 |
-
|
2162 |
-
|
2163 |
-
|
2164 |
-
|
2165 |
-
|
2166 |
-
|
2167 |
-
|
2168 |
-
|
2169 |
-
|
2170 |
-
|
2171 |
-
|
2172 |
-
|
2173 |
-
|
2174 |
-
|
2175 |
-
|
2176 |
-
|
2177 |
-
|
2178 |
-
|
2179 |
-
|
2180 |
-
|
2181 |
-
|
2182 |
-
|
2183 |
-
|
2184 |
-
|
2185 |
-
|
2186 |
-
|
2187 |
-
|
2188 |
-
|
2189 |
-
|
2190 |
-
|
2191 |
-
|
2192 |
-
|
2193 |
-
|
2194 |
-
|
2195 |
-
|
2196 |
-
|
2197 |
-
|
2198 |
-
|
2199 |
-
|
2200 |
-
|
2201 |
-
|
2202 |
-
|
2203 |
-
|
2204 |
-
|
2205 |
-
|
2206 |
-
|
2207 |
-
|
2208 |
-
|
2209 |
-
|
2210 |
-
= $
|
2211 |
-
|
2212 |
-
|
2213 |
-
|
2214 |
-
|
2215 |
-
|
2216 |
-
|
2217 |
-
|
2218 |
-
|
2219 |
-
|
2220 |
-
|
2221 |
-
|
2222 |
-
|
2223 |
-
|
2224 |
-
|
2225 |
-
|
2226 |
-
|
2227 |
-
|
2228 |
-
|
2229 |
-
|
2230 |
-
|
2231 |
-
|
2232 |
-
|
2233 |
-
|
2234 |
-
|
2235 |
-
|
2236 |
-
$
|
2237 |
-
|
2238 |
-
|
2239 |
-
|
2240 |
-
|
2241 |
-
|
2242 |
-
|
2243 |
-
|
2244 |
-
|
2245 |
-
|
2246 |
-
|
2247 |
-
|
2248 |
-
|
2249 |
-
|
2250 |
-
|
2251 |
-
|
2252 |
-
|
2253 |
-
|
2254 |
-
|
2255 |
-
|
2256 |
-
|
2257 |
-
|
2258 |
-
|
2259 |
-
|
2260 |
-
|
2261 |
-
|
2262 |
-
|
2263 |
-
|
2264 |
-
|
2265 |
-
|
2266 |
-
|
2267 |
-
|
2268 |
-
|
2269 |
-
|
2270 |
-
|
2271 |
-
|
2272 |
-
|
2273 |
-
|
2274 |
-
|
2275 |
-
|
2276 |
-
|
2277 |
-
|
2278 |
-
|
2279 |
-
|
2280 |
-
|
2281 |
-
|
2282 |
-
|
2283 |
-
|
2284 |
-
|
2285 |
-
|
2286 |
-
|
2287 |
-
|
2288 |
-
|
2289 |
-
|
2290 |
-
|
2291 |
-
|
2292 |
-
|
2293 |
-
|
2294 |
-
|
2295 |
-
|
2296 |
-
|
2297 |
-
|
2298 |
-
|
2299 |
-
|
2300 |
-
|
2301 |
-
|
2302 |
-
|
2303 |
-
|
2304 |
-
|
2305 |
-
|
2306 |
-
|
2307 |
-
|
2308 |
-
|
2309 |
-
|
2310 |
-
|
2311 |
-
|
2312 |
-
|
2313 |
-
|
2314 |
-
|
2315 |
-
|
2316 |
-
|
2317 |
-
|
2318 |
-
|
2319 |
-
|
2320 |
-
|
2321 |
-
|
2322 |
-
|
2323 |
-
|
2324 |
-
|
2325 |
-
|
2326 |
-
|
2327 |
-
|
2328 |
-
|
2329 |
-
|
2330 |
-
|
2331 |
-
|
2332 |
-
|
2333 |
-
|
2334 |
-
|
2335 |
-
|
2336 |
-
|
2337 |
-
|
2338 |
-
|
2339 |
-
|
2340 |
-
|
2341 |
-
|
2342 |
-
|
2343 |
-
|
2344 |
-
|
2345 |
-
|
2346 |
-
|
2347 |
-
|
2348 |
-
|
2349 |
-
}
|
2350 |
-
|
2351 |
-
//
|
2352 |
-
|
2353 |
-
if(
|
2354 |
-
$
|
2355 |
-
|
2356 |
-
|
2357 |
-
|
2358 |
-
|
2359 |
-
|
2360 |
-
|
2361 |
-
|
2362 |
-
|
2363 |
-
|
2364 |
-
|
2365 |
-
|
2366 |
-
|
2367 |
-
|
2368 |
-
|
2369 |
-
|
2370 |
-
|
2371 |
-
|
2372 |
-
|
2373 |
-
|
2374 |
-
|
2375 |
-
|
2376 |
-
|
2377 |
-
|
2378 |
-
|
2379 |
-
|
2380 |
-
|
2381 |
-
|
2382 |
-
|
2383 |
-
|
2384 |
-
|
2385 |
-
|
2386 |
-
|
2387 |
-
|
2388 |
-
|
2389 |
-
|
2390 |
-
|
2391 |
-
|
2392 |
-
|
2393 |
-
|
2394 |
-
|
2395 |
-
|
2396 |
-
|
2397 |
-
|
2398 |
-
|
2399 |
-
|
2400 |
-
|
2401 |
-
|
2402 |
-
|
2403 |
-
|
2404 |
-
|
2405 |
-
|
2406 |
-
|
2407 |
-
|
2408 |
-
|
2409 |
-
|
2410 |
-
|
2411 |
-
|
2412 |
-
|
2413 |
-
|
2414 |
-
|
2415 |
-
|
2416 |
-
|
2417 |
-
|
2418 |
-
|
2419 |
-
|
2420 |
-
|
2421 |
-
|
2422 |
-
|
2423 |
-
|
2424 |
-
|
2425 |
-
|
2426 |
-
|
2427 |
-
|
2428 |
-
|
2429 |
-
|
2430 |
-
|
2431 |
-
|
2432 |
-
|
2433 |
-
|
2434 |
-
|
2435 |
-
|
2436 |
-
|
2437 |
-
|
2438 |
-
|
2439 |
-
|
2440 |
-
|
2441 |
-
|
2442 |
-
|
2443 |
-
|
2444 |
-
|
2445 |
-
|
2446 |
-
|
2447 |
-
|
2448 |
-
|
2449 |
-
|
2450 |
-
|
2451 |
-
|
2452 |
-
|
2453 |
-
|
2454 |
-
|
2455 |
-
|
2456 |
-
|
2457 |
-
|
2458 |
-
|
2459 |
-
|
2460 |
-
|
2461 |
-
|
2462 |
-
|
2463 |
-
|
2464 |
-
|
2465 |
-
|
2466 |
-
|
2467 |
-
|
2468 |
-
|
2469 |
-
|
2470 |
-
|
2471 |
-
|
2472 |
-
|
2473 |
-
|
2474 |
-
|
2475 |
-
|
2476 |
-
|
2477 |
-
|
2478 |
-
|
2479 |
-
|
2480 |
-
|
2481 |
-
|
2482 |
-
|
2483 |
-
|
2484 |
-
|
2485 |
-
|
2486 |
-
|
2487 |
-
|
2488 |
-
}
|
2489 |
-
|
2490 |
-
|
2491 |
-
|
2492 |
-
|
2493 |
-
|
2494 |
-
|
2495 |
-
|
2496 |
-
|
2497 |
-
|
2498 |
-
|
2499 |
-
|
2500 |
-
|
2501 |
-
|
2502 |
-
|
2503 |
-
|
2504 |
-
|
2505 |
-
|
2506 |
-
|
2507 |
-
|
2508 |
-
|
2509 |
-
|
2510 |
-
|
2511 |
-
|
2512 |
-
|
2513 |
-
|
2514 |
-
|
2515 |
-
|
2516 |
-
|
2517 |
-
|
2518 |
-
|
2519 |
-
|
2520 |
-
|
2521 |
-
|
2522 |
-
|
2523 |
-
|
2524 |
-
|
2525 |
-
|
2526 |
-
|
2527 |
-
|
2528 |
-
|
2529 |
-
|
2530 |
-
|
2531 |
-
|
2532 |
-
|
2533 |
-
|
2534 |
-
|
2535 |
-
|
2536 |
-
|
2537 |
-
|
2538 |
-
|
2539 |
-
|
2540 |
-
|
2541 |
-
|
2542 |
-
|
2543 |
-
|
2544 |
-
|
2545 |
-
|
2546 |
-
|
2547 |
-
|
2548 |
-
|
2549 |
-
|
2550 |
-
|
2551 |
-
|
2552 |
-
|
2553 |
-
|
2554 |
-
|
2555 |
-
|
2556 |
-
|
2557 |
-
|
2558 |
-
|
2559 |
-
|
2560 |
-
|
2561 |
-
|
2562 |
-
|
2563 |
-
|
2564 |
-
|
2565 |
-
|
2566 |
-
|
2567 |
-
|
2568 |
-
|
2569 |
-
|
2570 |
-
|
2571 |
-
|
2572 |
-
|
2573 |
-
|
2574 |
-
|
2575 |
-
|
2576 |
-
|
2577 |
-
|
2578 |
-
|
2579 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class WP_Installer{
|
4 |
+
protected static $_instance = null;
|
5 |
+
|
6 |
+
public $settings = array();
|
7 |
+
|
8 |
+
private $repositories = array();
|
9 |
+
|
10 |
+
protected $api_debug = '';
|
11 |
+
|
12 |
+
private $config = array();
|
13 |
+
|
14 |
+
protected $_plugins_renew_warnings = array();
|
15 |
+
|
16 |
+
protected $_gz_on = false;
|
17 |
+
|
18 |
+
private $admin_messages = array();
|
19 |
+
|
20 |
+
private $_using_icl = false;
|
21 |
+
private $_wpml_version = false;
|
22 |
+
|
23 |
+
private $package_source = array();
|
24 |
+
|
25 |
+
const SITE_KEY_VALIDATION_SOURCE_OTHER = 0;
|
26 |
+
const SITE_KEY_VALIDATION_SOURCE_DOWNLOAD_SPECIFIC = 1;
|
27 |
+
const SITE_KEY_VALIDATION_SOURCE_DOWNLOAD_REPORT = 2;
|
28 |
+
const SITE_KEY_VALIDATION_SOURCE_REGISTRATION = 3;
|
29 |
+
const SITE_KEY_VALIDATION_SOURCE_REVALIDATION = 4;
|
30 |
+
const SITE_KEY_VALIDATION_SOURCE_UPDATES_CHECK = 5;
|
31 |
+
|
32 |
+
public $dependencies;
|
33 |
+
|
34 |
+
public static function instance() {
|
35 |
+
|
36 |
+
if ( is_null( self::$_instance ) ) {
|
37 |
+
self::$_instance = new self();
|
38 |
+
}
|
39 |
+
|
40 |
+
return self::$_instance;
|
41 |
+
}
|
42 |
+
|
43 |
+
public function __construct(){
|
44 |
+
|
45 |
+
if(!is_admin() || !is_user_logged_in()) return; //Only for admin
|
46 |
+
|
47 |
+
$this->_gz_on = function_exists('gzuncompress') && function_exists('gzcompress');
|
48 |
+
$this->settings = $this->get_settings();
|
49 |
+
|
50 |
+
add_action('admin_notices', array($this, 'show_site_key_nags'));
|
51 |
+
|
52 |
+
add_action('admin_notices', array($this, 'show_admin_messages'));
|
53 |
+
|
54 |
+
add_action('admin_init', array($this, 'load_embedded_plugins'), 0);
|
55 |
+
|
56 |
+
add_action('admin_menu', array($this, 'menu_setup'));
|
57 |
+
add_action('network_admin_menu', array($this, 'menu_setup'));
|
58 |
+
|
59 |
+
if(defined('DOING_AJAX') && isset($_POST['action']) && $_POST['action'] == 'installer_download_plugin'){
|
60 |
+
add_filter( 'site_transient_update_plugins', array( $this, 'plugins_upgrade_check') );
|
61 |
+
}
|
62 |
+
add_filter('plugins_api', array( $this, 'custom_plugins_api_call'), 10, 3);
|
63 |
+
add_filter('pre_set_site_transient_update_plugins', array( $this, 'plugins_upgrade_check'));
|
64 |
+
|
65 |
+
// register repositories
|
66 |
+
$this->load_repositories_list();
|
67 |
+
|
68 |
+
if( empty($this->settings['last_repositories_update']) || time() - $this->settings['last_repositories_update'] > 86400
|
69 |
+
|| ( isset($_GET['force-check']) && $_GET['force-check'] == 1 ) ){
|
70 |
+
$this->refresh_repositories_data();
|
71 |
+
}
|
72 |
+
|
73 |
+
// default config
|
74 |
+
$this->config['plugins_install_tab'] = false;
|
75 |
+
|
76 |
+
add_action('init', array($this, 'init'));
|
77 |
+
|
78 |
+
//add_filter('wp_installer_buy_url', array($this, 'append_parameters_to_buy_url'));
|
79 |
+
|
80 |
+
add_action('init', array($this,'load_locale'));
|
81 |
+
|
82 |
+
}
|
83 |
+
|
84 |
+
public function get_repositories() {
|
85 |
+
|
86 |
+
return $this->repositories;
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
public function set_config($key, $value){
|
91 |
+
|
92 |
+
$this->config[$key] = $value;
|
93 |
+
|
94 |
+
}
|
95 |
+
|
96 |
+
public function init(){
|
97 |
+
global $pagenow;
|
98 |
+
|
99 |
+
$this->dependencies = new Installer_Dependencies;
|
100 |
+
|
101 |
+
if(empty($this->settings['_pre_1_0_clean_up'])) {
|
102 |
+
$this->_pre_1_0_clean_up();
|
103 |
+
}
|
104 |
+
|
105 |
+
$this->settings = $this->_old_products_format_backwards_compatibility($this->settings);
|
106 |
+
|
107 |
+
if ( !function_exists( 'get_plugins' ) ) {
|
108 |
+
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
109 |
+
}
|
110 |
+
|
111 |
+
$this->_using_icl = function_exists('wpml_site_uses_icl') && wpml_site_uses_icl();
|
112 |
+
$this->_wpml_version = defined('ICL_SITEPRESS_VERSION') ? ICL_SITEPRESS_VERSION : '';
|
113 |
+
|
114 |
+
wp_enqueue_script('installer-admin', $this->res_url() . '/res/js/admin.js', array('jquery'), $this->version());
|
115 |
+
wp_enqueue_style('installer-admin', $this->res_url() . '/res/css/admin.css', array(), $this->version());
|
116 |
+
|
117 |
+
$translation_array = array(
|
118 |
+
'installing' => __( 'Installing %s', 'installer' ),
|
119 |
+
'updating' => __( 'Updating %s', 'installer' ),
|
120 |
+
'activating' => __( 'Activating %s', 'installer' )
|
121 |
+
);
|
122 |
+
|
123 |
+
wp_localize_script( 'installer-admin', 'installer_strings', $translation_array );
|
124 |
+
|
125 |
+
if($pagenow == 'plugins.php'){
|
126 |
+
add_action('admin_notices', array($this, 'setup_plugins_page_notices'));
|
127 |
+
add_action('admin_notices', array($this, 'setup_plugins_renew_warnings'), 10);
|
128 |
+
add_action('admin_notices', array($this, 'queue_plugins_renew_warnings'), 20);
|
129 |
+
|
130 |
+
add_action('admin_init', array($this, 'setup_plugins_action_links'));
|
131 |
+
|
132 |
+
}
|
133 |
+
|
134 |
+
if($this->is_repositories_page()){
|
135 |
+
add_action('admin_init', array($this, 'validate_repository_subscription'));
|
136 |
+
}
|
137 |
+
|
138 |
+
if(defined('DOING_AJAX')){
|
139 |
+
add_action('wp_ajax_save_site_key', array($this, 'save_site_key'));
|
140 |
+
add_action('wp_ajax_remove_site_key', array($this, 'remove_site_key_ajax'));
|
141 |
+
add_action('wp_ajax_update_site_key', array($this, 'update_site_key'));
|
142 |
+
|
143 |
+
add_action('wp_ajax_installer_download_plugin', array($this, 'download_plugin_ajax_handler'));
|
144 |
+
add_action('wp_ajax_installer_activate_plugin', array($this, 'activate_plugin'));
|
145 |
+
|
146 |
+
add_action('wp_ajax_installer_dismiss_nag', array($this, 'dismiss_nag'));
|
147 |
+
}
|
148 |
+
|
149 |
+
if($pagenow == 'update.php'){
|
150 |
+
if(isset($_GET['action']) && $_GET['action'] == 'update-selected'){
|
151 |
+
add_action('admin_head', array($this, 'plugin_upgrade_custom_errors')); //iframe/bulk
|
152 |
+
}else{
|
153 |
+
add_action('all_admin_notices', array($this, 'plugin_upgrade_custom_errors')); //regular/singular
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
// WP 4.2
|
158 |
+
if(defined('DOING_AJAX')){
|
159 |
+
add_action('wp_ajax_update-plugin', array($this, 'plugin_upgrade_custom_errors'), 0); // high priority, before WP
|
160 |
+
}
|
161 |
+
|
162 |
+
//Include theme support
|
163 |
+
include_once $this->plugin_path() . '/includes/class-installer-theme.php';
|
164 |
+
|
165 |
+
// Extra information about the source of Installer
|
166 |
+
$package_source_file = $this->plugin_path() . '/installer-source.json';
|
167 |
+
if( file_exists( $package_source_file ) ){
|
168 |
+
$this->package_source = json_decode( file_get_contents( $package_source_file ) );
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
protected function log($message){
|
173 |
+
if( defined('WPML_INSTALLER_LOGGING') && WPML_INSTALLER_LOGGING ){
|
174 |
+
if($fh = @fopen( $this->plugin_path() . '/installer.log', 'a' )){
|
175 |
+
fwrite($fh, current_time( 'mysql' ) . "\t" . $message . "\n");
|
176 |
+
}
|
177 |
+
}
|
178 |
+
}
|
179 |
+
|
180 |
+
public function register_admin_message($text, $type = 'updated'){
|
181 |
+
$this->admin_messages[] = array('text' => $text, 'type' => $type);
|
182 |
+
}
|
183 |
+
|
184 |
+
public function show_admin_messages(){
|
185 |
+
if(!empty($this->admin_messages)){
|
186 |
+
$types = array( 'error', 'updated', 'notice' );
|
187 |
+
foreach($this->admin_messages as $message){
|
188 |
+
$class = in_array( $message['type'], $types ) ? $message['type'] : 'updated';
|
189 |
+
?>
|
190 |
+
<div class="<?php echo $class ?>">
|
191 |
+
<p>
|
192 |
+
<?php echo $message['text'] ?>
|
193 |
+
</p>
|
194 |
+
</div>
|
195 |
+
<?php
|
196 |
+
}
|
197 |
+
}
|
198 |
+
}
|
199 |
+
|
200 |
+
public function load_locale(){
|
201 |
+
$locale = get_locale();
|
202 |
+
$locale = apply_filters( 'plugin_locale', $locale, 'installer' );
|
203 |
+
$mo_file = $this->plugin_path() . '/locale/installer-' . $locale . '.mo';
|
204 |
+
if(file_exists($mo_file)){
|
205 |
+
load_textdomain( 'installer', $mo_file );
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
public function load_embedded_plugins(){
|
210 |
+
if(file_exists($this->plugin_path() . '/embedded-plugins' )) {
|
211 |
+
include_once $this->plugin_path() . '/embedded-plugins/embedded-plugins.class.php';
|
212 |
+
$this->installer_embedded_plugins = new Installer_Embedded_Plugins();
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
+
public function menu_setup(){
|
217 |
+
global $pagenow;
|
218 |
+
|
219 |
+
if(is_multisite() && !is_network_admin()){
|
220 |
+
$this->menu_multisite_redirect();
|
221 |
+
add_options_page(__('Installer', 'installer'), __('Installer', 'installer'), 'manage_options', 'installer', array($this, 'show_products')) ;
|
222 |
+
}else{
|
223 |
+
if($this->config['plugins_install_tab'] && is_admin() && $pagenow == 'plugin-install.php'){
|
224 |
+
// Default GUI, under Plugins -> Install
|
225 |
+
add_filter('install_plugins_tabs', array($this, 'add_install_plugins_tab'));
|
226 |
+
add_action('install_plugins_commercial', array($this, 'show_products'));
|
227 |
+
}
|
228 |
+
}
|
229 |
+
|
230 |
+
}
|
231 |
+
|
232 |
+
public function menu_url(){
|
233 |
+
if(is_multisite()){
|
234 |
+
if(is_network_admin()){
|
235 |
+
$url = network_admin_url('plugin-install.php?tab=commercial');
|
236 |
+
}else{
|
237 |
+
$url = admin_url('options-general.php?page=installer');
|
238 |
+
}
|
239 |
+
}else{
|
240 |
+
$url = admin_url('plugin-install.php?tab=commercial');
|
241 |
+
}
|
242 |
+
return $url;
|
243 |
+
}
|
244 |
+
|
245 |
+
private function menu_multisite_redirect(){
|
246 |
+
global $pagenow;
|
247 |
+
|
248 |
+
if($pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial'){
|
249 |
+
wp_redirect($this->menu_url());
|
250 |
+
exit;
|
251 |
+
}
|
252 |
+
|
253 |
+
}
|
254 |
+
|
255 |
+
private function _pre_1_0_clean_up(){
|
256 |
+
global $wpdb;
|
257 |
+
|
258 |
+
if(!defined('WPRC_VERSION')){
|
259 |
+
$old_tables = array(
|
260 |
+
$wpdb->prefix . 'wprc_cached_requests',
|
261 |
+
$wpdb->prefix . 'wprc_extension_types',
|
262 |
+
$wpdb->prefix . 'wprc_extensions',
|
263 |
+
$wpdb->prefix . 'wprc_repositories',
|
264 |
+
$wpdb->prefix . 'wprc_repositories_relationships',
|
265 |
+
);
|
266 |
+
|
267 |
+
foreach($old_tables as $table){
|
268 |
+
$wpdb->query(sprintf("DROP TABLE IF EXISTS %s", $table));
|
269 |
+
}
|
270 |
+
|
271 |
+
}
|
272 |
+
|
273 |
+
$this->settings['_pre_1_0_clean_up'] = true;
|
274 |
+
$this->save_settings();
|
275 |
+
}
|
276 |
+
|
277 |
+
public function setup_plugins_action_links(){
|
278 |
+
|
279 |
+
$plugins = get_plugins();
|
280 |
+
|
281 |
+
$repositories_plugins = array();
|
282 |
+
|
283 |
+
if( !empty($this->settings['repositories']) ) {
|
284 |
+
|
285 |
+
foreach ( $this->settings['repositories'] as $repository_id => $repository ) {
|
286 |
+
|
287 |
+
foreach ( $repository['data']['packages'] as $package ) {
|
288 |
+
|
289 |
+
foreach ( $package['products'] as $product ) {
|
290 |
+
|
291 |
+
foreach ( $product['plugins'] as $plugin_slug ) {
|
292 |
+
|
293 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
294 |
+
|
295 |
+
if ( !isset($repositories_plugins[$repository_id][$download['slug']]) ) {
|
296 |
+
$repositories_plugins[$repository_id][$download['slug']] = array(
|
297 |
+
'name' => $download['name'],
|
298 |
+
'registered' => $this->plugin_is_registered( $repository_id, $download['slug'] ) ? 1 : 0
|
299 |
+
);
|
300 |
+
}
|
301 |
+
|
302 |
+
}
|
303 |
+
|
304 |
+
}
|
305 |
+
|
306 |
+
}
|
307 |
+
|
308 |
+
foreach ( $plugins as $plugin_id => $plugin ) {
|
309 |
+
|
310 |
+
$wp_plugin_slug = dirname( $plugin_id );
|
311 |
+
if ( empty($wp_plugin_slug) ) {
|
312 |
+
$wp_plugin_slug = basename( $plugin_id, '.php' );
|
313 |
+
}
|
314 |
+
|
315 |
+
foreach ( $repositories_plugins as $repository_id => $r_plugins ) {
|
316 |
+
|
317 |
+
foreach ( $r_plugins as $slug => $r_plugin ) {
|
318 |
+
|
319 |
+
if ( $wp_plugin_slug == $slug || $r_plugin['name'] == $plugin['Name'] || $r_plugin['name'] == $plugin['Title'] ) { //match order: slug, name, title
|
320 |
+
|
321 |
+
if ( $r_plugin['registered'] ) {
|
322 |
+
add_filter( 'plugin_action_links_' . $plugin_id, array($this, 'plugins_action_links_registered') );
|
323 |
+
} else {
|
324 |
+
add_filter( 'plugin_action_links_' . $plugin_id, array($this, 'plugins_action_links_not_registered') );
|
325 |
+
}
|
326 |
+
|
327 |
+
}
|
328 |
+
|
329 |
+
}
|
330 |
+
|
331 |
+
}
|
332 |
+
|
333 |
+
|
334 |
+
}
|
335 |
+
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
}
|
340 |
+
|
341 |
+
public function plugins_action_links_registered($links){
|
342 |
+
$links[] = '<a href="' . $this->menu_url() . '">' . __('Registered', 'installer') . '</a>';
|
343 |
+
return $links;
|
344 |
+
}
|
345 |
+
|
346 |
+
public function plugins_action_links_not_registered($links){
|
347 |
+
$links[] = '<a href="' . $this->menu_url() . '">' . __('Register', 'installer') . '</a>';
|
348 |
+
return $links;
|
349 |
+
}
|
350 |
+
|
351 |
+
public function plugin_is_registered($repository_id, $slug){
|
352 |
+
|
353 |
+
$registered = false;
|
354 |
+
|
355 |
+
if( $this->repository_has_valid_subscription($repository_id) ){
|
356 |
+
|
357 |
+
$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
358 |
+
$r_plugins = array();
|
359 |
+
|
360 |
+
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
|
361 |
+
|
362 |
+
foreach($package['products'] as $product){
|
363 |
+
|
364 |
+
if( $product['subscription_type'] == $subscription_type || $this->have_superior_subscription($subscription_type, $product) ) {
|
365 |
+
|
366 |
+
foreach ($product['plugins'] as $plugin_slug) {
|
367 |
+
|
368 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
369 |
+
|
370 |
+
if (!isset($rep_plugins[$download['slug']])) {
|
371 |
+
$r_plugins[$download['slug']] = $download['slug'];
|
372 |
+
}
|
373 |
+
|
374 |
+
}
|
375 |
+
|
376 |
+
}
|
377 |
+
|
378 |
+
}
|
379 |
+
|
380 |
+
}
|
381 |
+
|
382 |
+
$registered = isset($r_plugins[$slug]);
|
383 |
+
|
384 |
+
}
|
385 |
+
|
386 |
+
|
387 |
+
return $registered;
|
388 |
+
|
389 |
+
}
|
390 |
+
|
391 |
+
public function version(){
|
392 |
+
return WP_INSTALLER_VERSION;
|
393 |
+
}
|
394 |
+
|
395 |
+
public function plugin_path() {
|
396 |
+
return untrailingslashit( plugin_dir_path( dirname(__FILE__) ) );
|
397 |
+
}
|
398 |
+
|
399 |
+
public function plugin_url() {
|
400 |
+
if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
|
401 |
+
$url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
|
402 |
+
}else{
|
403 |
+
$url = untrailingslashit( plugins_url( '/', dirname(__FILE__) ) );
|
404 |
+
}
|
405 |
+
|
406 |
+
return $url;
|
407 |
+
}
|
408 |
+
|
409 |
+
public function is_repositories_page(){
|
410 |
+
global $pagenow;
|
411 |
+
|
412 |
+
return $pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial';
|
413 |
+
}
|
414 |
+
|
415 |
+
public function res_url(){
|
416 |
+
if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
|
417 |
+
$url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
|
418 |
+
}else{
|
419 |
+
$url = $this->plugin_url();
|
420 |
+
}
|
421 |
+
return $url;
|
422 |
+
}
|
423 |
+
|
424 |
+
public function save_settings(){
|
425 |
+
|
426 |
+
$_settings = serialize($this->settings);
|
427 |
+
if($this->_gz_on){
|
428 |
+
$_settings = gzcompress($_settings);
|
429 |
+
}
|
430 |
+
$_settings = base64_encode($_settings);
|
431 |
+
|
432 |
+
update_option( 'wp_installer_settings', $_settings );
|
433 |
+
|
434 |
+
if( is_multisite() && is_main_site() && isset($this->settings['repositories']) ){
|
435 |
+
$network_settings = array();
|
436 |
+
|
437 |
+
foreach( $this->settings['repositories'] as $rep_id => $repository ){
|
438 |
+
if( isset($repository['subscription']) )
|
439 |
+
$network_settings[$rep_id] = $repository['subscription'];
|
440 |
+
}
|
441 |
+
|
442 |
+
update_site_option( 'wp_installer_network', $network_settings );
|
443 |
+
|
444 |
+
|
445 |
+
}
|
446 |
+
|
447 |
+
}
|
448 |
+
|
449 |
+
public function get_settings($refresh = false){
|
450 |
+
|
451 |
+
if($refresh || empty($this->settings)){
|
452 |
+
|
453 |
+
$_settings = get_option('wp_installer_settings');
|
454 |
+
|
455 |
+
|
456 |
+
if (is_array($_settings) || empty($_settings)) { //backward compatibility 1.1
|
457 |
+
$this->settings = $_settings;
|
458 |
+
|
459 |
+
} else {
|
460 |
+
$_settings = base64_decode($_settings);
|
461 |
+
if ($this->_gz_on) {
|
462 |
+
$_settings = gzuncompress($_settings);
|
463 |
+
}
|
464 |
+
$this->settings = unserialize($_settings);
|
465 |
+
}
|
466 |
+
|
467 |
+
if (is_multisite() && isset($this->settings['repositories'])) {
|
468 |
+
$network_settings = maybe_unserialize(get_site_option('wp_installer_network'));
|
469 |
+
if ($network_settings) {
|
470 |
+
foreach ($this->settings['repositories'] as $rep_id => $repository) {
|
471 |
+
if (isset($network_settings[$rep_id])) {
|
472 |
+
$this->settings['repositories'][$rep_id]['subscription'] = $network_settings[$rep_id];
|
473 |
+
}
|
474 |
+
}
|
475 |
+
}
|
476 |
+
}
|
477 |
+
|
478 |
+
$this->load_hardcoded_site_keys();
|
479 |
+
|
480 |
+
$this->settings = $this->_pre_1_6_backwards_compatibility($this->settings);
|
481 |
+
|
482 |
+
$this->settings = $this->_old_products_format_backwards_compatibility($this->settings);
|
483 |
+
|
484 |
+
}
|
485 |
+
|
486 |
+
return $this->settings;
|
487 |
+
}
|
488 |
+
|
489 |
+
private function load_hardcoded_site_keys(){
|
490 |
+
|
491 |
+
if( !empty( $this->settings['repositories'] ) ) {
|
492 |
+
foreach ( $this->settings['repositories'] as $repository_id => $repository ) {
|
493 |
+
|
494 |
+
if ( $site_key = self::get_repository_hardcoded_site_key( $repository_id ) ) {
|
495 |
+
|
496 |
+
$site_key_missing = empty($this->settings['repositories'][$repository_id]['subscription']['data']);
|
497 |
+
$site_key_changed = !$site_key_missing &&
|
498 |
+
$this->settings['repositories'][$repository_id]['subscription']['key'] != $site_key;
|
499 |
+
|
500 |
+
if ( $site_key_missing || $site_key_changed ) {
|
501 |
+
|
502 |
+
if ( !function_exists( 'get_plugins' ) ) {
|
503 |
+
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
504 |
+
}
|
505 |
+
$this->load_repositories_list();
|
506 |
+
$response = $this->save_site_key(
|
507 |
+
array(
|
508 |
+
'repository_id' => $repository_id,
|
509 |
+
'site_key' => $site_key,
|
510 |
+
'return' => true,
|
511 |
+
'nonce' => wp_create_nonce( 'save_site_key_' . $repository_id )
|
512 |
+
)
|
513 |
+
);
|
514 |
+
|
515 |
+
if ( !empty($response['error']) ) {
|
516 |
+
$this->remove_site_key( $repository_id );
|
517 |
+
|
518 |
+
$this->admin_messages[] = array(
|
519 |
+
'type' => 'error',
|
520 |
+
'text' => sprintf( __( 'You are using an invalid site key defined as the constant %s (most likely in wp-config.php).
|
521 |
+
Please remove it or use the correct value in order to be able to register correctly.', 'installer' ), 'OTGS_INSTALLER_SITE_KEY_' . strtoupper( $repository_id ) )
|
522 |
+
);
|
523 |
+
|
524 |
+
}
|
525 |
+
|
526 |
+
}
|
527 |
+
|
528 |
+
}
|
529 |
+
|
530 |
+
}
|
531 |
+
}
|
532 |
+
|
533 |
+
}
|
534 |
+
|
535 |
+
public static function get_repository_hardcoded_site_key( $repository_id ){
|
536 |
+
|
537 |
+
$site_key = false;
|
538 |
+
|
539 |
+
$site_key_constant = 'OTGS_INSTALLER_SITE_KEY_' . strtoupper( $repository_id );
|
540 |
+
if( defined( $site_key_constant ) ){
|
541 |
+
$site_key = constant( $site_key_constant );
|
542 |
+
}
|
543 |
+
|
544 |
+
return $site_key;
|
545 |
+
}
|
546 |
+
|
547 |
+
//backward compatibility, will remove 'basename' in version 1.8
|
548 |
+
private function _pre_1_6_backwards_compatibility($settings){
|
549 |
+
|
550 |
+
if( version_compare($this->version(), '1.8', '<') && !empty($settings['repositories']) ){
|
551 |
+
|
552 |
+
foreach ($settings['repositories'] as $repository_id => $repository) {
|
553 |
+
|
554 |
+
foreach ($repository['data']['downloads']['plugins'] as $slug => $download) {
|
555 |
+
|
556 |
+
$settings['repositories'][$repository_id]['data']['downloads']['plugins'][$slug]['slug'] = $download['basename'];
|
557 |
+
|
558 |
+
}
|
559 |
+
}
|
560 |
+
|
561 |
+
}
|
562 |
+
|
563 |
+
return $settings;
|
564 |
+
|
565 |
+
}
|
566 |
+
|
567 |
+
//backward compatibility - support old products list format (downloads under products instead of global downloads list)
|
568 |
+
private function _old_products_format_backwards_compatibility($settings){
|
569 |
+
|
570 |
+
if( version_compare($this->version(), '1.8', '<') && !empty($settings['repositories']) && empty($this->_old_products_format_backwards_compatibility) ) {
|
571 |
+
|
572 |
+
foreach ($settings['repositories'] as $repository_id => $repository) {
|
573 |
+
|
574 |
+
$populate_downloads = false;
|
575 |
+
|
576 |
+
foreach ($repository['data']['packages'] as $package_id => $package) {
|
577 |
+
|
578 |
+
foreach ($package['products'] as $product_id => $product) {
|
579 |
+
|
580 |
+
if (!isset($product['plugins'])) {
|
581 |
+
|
582 |
+
$populate_downloads = true;
|
583 |
+
|
584 |
+
foreach ($product['downloads'] as $download_id => $download) {
|
585 |
+
|
586 |
+
$settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['plugins'][] = $download['slug'];
|
587 |
+
|
588 |
+
}
|
589 |
+
|
590 |
+
}
|
591 |
+
|
592 |
+
}
|
593 |
+
|
594 |
+
}
|
595 |
+
|
596 |
+
if ($populate_downloads) {
|
597 |
+
|
598 |
+
// Add downloads branch
|
599 |
+
foreach ($repository['data']['packages'] as $package_id => $package) {
|
600 |
+
|
601 |
+
foreach ($package['products'] as $product_id => $product) {
|
602 |
+
|
603 |
+
foreach ($product['downloads'] as $download_id => $download) {
|
604 |
+
|
605 |
+
if (!isset($settings['repositories'][$repository_id]['data']['downloads']['plugins'][$download['slug']])) {
|
606 |
+
$settings['repositories'][$repository_id]['data']['downloads']['plugins'][$download['slug']] = $download;
|
607 |
+
}
|
608 |
+
|
609 |
+
$settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['plugins'][] = $download['slug'];
|
610 |
+
}
|
611 |
+
|
612 |
+
unset($settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['downloads']);
|
613 |
+
|
614 |
+
}
|
615 |
+
|
616 |
+
}
|
617 |
+
|
618 |
+
}
|
619 |
+
|
620 |
+
}
|
621 |
+
|
622 |
+
$this->_old_products_format_backwards_compatibility = true;
|
623 |
+
|
624 |
+
}
|
625 |
+
|
626 |
+
return $settings;
|
627 |
+
|
628 |
+
}
|
629 |
+
|
630 |
+
public function get_installer_site_url( $repository_id = false ){
|
631 |
+
global $current_site;
|
632 |
+
|
633 |
+
$site_url = get_site_url();
|
634 |
+
|
635 |
+
if( $repository_id && is_multisite() && isset( $this->settings['repositories'] ) ){
|
636 |
+
$network_settings = maybe_unserialize( get_site_option('wp_installer_network') );
|
637 |
+
|
638 |
+
if ( isset( $network_settings[$repository_id] ) ) {
|
639 |
+
$site_url = get_site_url( $current_site->blog_id );
|
640 |
+
}
|
641 |
+
|
642 |
+
}
|
643 |
+
|
644 |
+
return $site_url;
|
645 |
+
}
|
646 |
+
|
647 |
+
public function show_site_key_nags(){
|
648 |
+
$screen = get_current_screen();
|
649 |
+
|
650 |
+
if($screen->base == 'settings_page_installer' || ($screen->base == 'plugin-install' && isset($_GET['tab']) && $_GET['tab'] == 'commercial')){
|
651 |
+
return;
|
652 |
+
}
|
653 |
+
|
654 |
+
if(!empty($this->config['site_key_nags'])){
|
655 |
+
|
656 |
+
foreach($this->config['site_key_nags'] as $nag){
|
657 |
+
|
658 |
+
if(!$this->repository_has_subscription($nag['repository_id'] )){
|
659 |
+
$show = true;
|
660 |
+
if(!empty($nag['condition_cb'])){
|
661 |
+
$show = call_user_func($nag['condition_cb']);
|
662 |
+
}
|
663 |
+
|
664 |
+
if(empty($this->settings['dismissed_nags'][$nag['repository_id']]) && $show){
|
665 |
+
echo '<div class="updated error otgs-is-dismissible"><p>';
|
666 |
+
printf(__("To get automatic updates, you need to register %s for this site. %sRegister %s%s", 'sitepress'),
|
667 |
+
$nag['product_name'], '<a class="button-primary" href="' . $this->menu_url() . '">', $nag['product_name'], '</a>');
|
668 |
+
|
669 |
+
echo '</p>';
|
670 |
+
echo '<span class="installer-dismiss-nag notice-dismiss" data-repository="' . $nag['repository_id'] . '"><span class="screen-reader-text">' . __('Dismiss', 'sitepress') . '</span></span>';
|
671 |
+
echo '</div>';
|
672 |
+
}
|
673 |
+
}
|
674 |
+
|
675 |
+
}
|
676 |
+
|
677 |
+
}
|
678 |
+
|
679 |
+
}
|
680 |
+
|
681 |
+
public function dismiss_nag(){
|
682 |
+
$this->settings['dismissed_nags'][$_POST['repository']] = 1;
|
683 |
+
|
684 |
+
$this->save_settings();
|
685 |
+
|
686 |
+
echo json_encode(array());
|
687 |
+
exit;
|
688 |
+
}
|
689 |
+
|
690 |
+
public function add_install_plugins_tab($tabs){
|
691 |
+
|
692 |
+
$tabs['commercial'] = __('Commercial', 'installer');
|
693 |
+
|
694 |
+
return $tabs;
|
695 |
+
}
|
696 |
+
|
697 |
+
public function load_repositories_list(){
|
698 |
+
global $wp_installer_instances;
|
699 |
+
|
700 |
+
foreach ($wp_installer_instances as $instance) {
|
701 |
+
|
702 |
+
if (file_exists(dirname($instance['bootfile']) . '/repositories.xml')) {
|
703 |
+
$config_file = dirname($instance['bootfile']) . '/repositories.xml';
|
704 |
+
|
705 |
+
if (file_exists(dirname($instance['bootfile']) . '/repositories.sandbox.xml')) {
|
706 |
+
$config_file = dirname($instance['bootfile']) . '/repositories.sandbox.xml';
|
707 |
+
add_filter('https_ssl_verify', '__return_false');
|
708 |
+
}
|
709 |
+
|
710 |
+
$repos = simplexml_load_file($config_file);
|
711 |
+
|
712 |
+
if($repos) {
|
713 |
+
foreach ($repos as $repo) {
|
714 |
+
$id = strval($repo->id);
|
715 |
+
|
716 |
+
$data['api-url'] = strval($repo->apiurl);
|
717 |
+
$data['products'] = strval($repo->products);
|
718 |
+
|
719 |
+
// excludes rule;
|
720 |
+
if (isset($this->config['repositories_exclude']) && in_array($id, $this->config['repositories_exclude'])) {
|
721 |
+
continue;
|
722 |
+
}
|
723 |
+
|
724 |
+
// includes rule;
|
725 |
+
if (isset($this->config['repositories_include']) && !in_array($id, $this->config['repositories_include'])) {
|
726 |
+
continue;
|
727 |
+
}
|
728 |
+
|
729 |
+
$this->repositories[$id] = $data;
|
730 |
+
|
731 |
+
}
|
732 |
+
}
|
733 |
+
|
734 |
+
}
|
735 |
+
}
|
736 |
+
|
737 |
+
}
|
738 |
+
|
739 |
+
public function filter_repositories_list(){
|
740 |
+
|
741 |
+
if(!empty($this->settings['repositories'])) {
|
742 |
+
foreach ($this->settings['repositories'] as $id => $repo_data) {
|
743 |
+
|
744 |
+
// excludes rule;
|
745 |
+
if (isset($this->config['repositories_exclude']) && in_array($id, $this->config['repositories_exclude'])) {
|
746 |
+
unset($this->settings['repositories'][$id]);
|
747 |
+
}
|
748 |
+
|
749 |
+
// includes rule;
|
750 |
+
if (isset($this->config['repositories_include']) && !in_array($id, $this->config['repositories_include'])) {
|
751 |
+
unset($this->settings['repositories'][$id]);
|
752 |
+
}
|
753 |
+
|
754 |
+
|
755 |
+
}
|
756 |
+
}
|
757 |
+
|
758 |
+
|
759 |
+
}
|
760 |
+
|
761 |
+
public function refresh_repositories_data(){
|
762 |
+
static $checked = false;
|
763 |
+
|
764 |
+
if( defined('OTGS_DISABLE_AUTO_UPDATES') && OTGS_DISABLE_AUTO_UPDATES && empty($_GET['force-check']) || $checked ){
|
765 |
+
|
766 |
+
if(empty($this->settings['repositories']) && $this->is_repositories_page()){
|
767 |
+
|
768 |
+
foreach($this->repositories as $id => $data) {
|
769 |
+
$repository_names[] = $id;
|
770 |
+
|
771 |
+
}
|
772 |
+
|
773 |
+
$error = sprintf(__("Installer cannot display the products information because the automatic updating for %s was explicitly disabled with the configuration below (usually in wp-config.php):", 'installer'), strtoupper( join(', ', $repository_names) ));
|
774 |
+
$error .= '<br /><br /><code>define("OTGS_DISABLE_AUTO_UPDATES", true);</code><br /><br />';
|
775 |
+
$error .= sprintf(__("In order to see the products information, please run the %smanual updates check%s to initialize the products list or (temporarily) remove the above code.", 'installer'), '<a href="' . admin_url('update-core.php') . '">', '</a>');
|
776 |
+
|
777 |
+
$this->register_admin_message($error, 'error');
|
778 |
+
|
779 |
+
|
780 |
+
}
|
781 |
+
|
782 |
+
return;
|
783 |
+
}
|
784 |
+
|
785 |
+
$checked = true;
|
786 |
+
|
787 |
+
foreach($this->repositories as $id => $data){
|
788 |
+
|
789 |
+
$response = wp_remote_get($data['products']);
|
790 |
+
|
791 |
+
if(is_wp_error($response)){
|
792 |
+
// http fallback
|
793 |
+
$data['products'] = preg_replace("@^https://@", 'http://', $data['products']);
|
794 |
+
$response = wp_remote_get($data['products']);
|
795 |
+
}
|
796 |
+
|
797 |
+
if(is_wp_error($response)){
|
798 |
+
|
799 |
+
$error = sprintf(__("Installer cannot contact our updates server to get information about the available products and check for new versions. If you are seeing this message for the first time, you can ignore it, as it may be a temporary communication problem. If the problem persists and your WordPress admin is slowing down, you can disable automated version checks. Add the following line to your wp-config.php file:", 'installer'), strtoupper($id));
|
800 |
+
$error .= '<br /><br /><code>define("OTGS_DISABLE_AUTO_UPDATES", true);</code>';
|
801 |
+
|
802 |
+
$this->register_admin_message($error, 'error');
|
803 |
+
|
804 |
+
continue;
|
805 |
+
}
|
806 |
+
|
807 |
+
if($response && isset($response['response']['code']) && $response['response']['code'] == 200){
|
808 |
+
$body = wp_remote_retrieve_body($response);
|
809 |
+
if($body){
|
810 |
+
$products = json_decode($body, true);
|
811 |
+
|
812 |
+
if(is_array($products)){
|
813 |
+
$this->settings['repositories'][$id]['data'] = $products;
|
814 |
+
$this->settings = $this->_pre_1_6_backwards_compatibility($this->settings);
|
815 |
+
}
|
816 |
+
}
|
817 |
+
|
818 |
+
}
|
819 |
+
|
820 |
+
$this->log( sprintf("Checked for %s updates: %s", $id, $data['products']) );
|
821 |
+
|
822 |
+
|
823 |
+
}
|
824 |
+
|
825 |
+
// cleanup
|
826 |
+
if(empty($this->settings['repositories'])){
|
827 |
+
$this->settings['repositories'] = array();
|
828 |
+
}
|
829 |
+
foreach($this->settings['repositories'] as $id => $data){
|
830 |
+
if(!in_array($id, array_keys($this->repositories))){
|
831 |
+
unset($this->settings['repositories'][$id]);
|
832 |
+
}
|
833 |
+
}
|
834 |
+
|
835 |
+
$this->settings['last_repositories_update']= time();
|
836 |
+
|
837 |
+
$this->save_settings();
|
838 |
+
|
839 |
+
}
|
840 |
+
|
841 |
+
public function show_products($args = array()){
|
842 |
+
|
843 |
+
$screen = get_current_screen();
|
844 |
+
|
845 |
+
if($screen->base == 'settings_page_installer'){ // settings page
|
846 |
+
echo '<div class="wrap">';
|
847 |
+
echo '<h2>' . __('Installer', 'installer') . '</h2>';
|
848 |
+
echo '<br />';
|
849 |
+
}
|
850 |
+
|
851 |
+
if(!is_array($args)) $args = array();
|
852 |
+
if(empty($args['template'])) $args['template'] = 'default';
|
853 |
+
|
854 |
+
$this->filter_repositories_list();
|
855 |
+
|
856 |
+
if(!empty($this->settings['repositories'])){
|
857 |
+
|
858 |
+
$this->localize_strings();
|
859 |
+
$this->set_filtered_prices($args);
|
860 |
+
$this->set_hierarchy_and_order();
|
861 |
+
|
862 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
863 |
+
|
864 |
+
if($args['template'] == 'compact'){
|
865 |
+
|
866 |
+
if(isset($args['repository']) && $args['repository'] == $repository_id){
|
867 |
+
include $this->plugin_path() . '/templates/products-compact.php';
|
868 |
+
}
|
869 |
+
|
870 |
+
}else{
|
871 |
+
|
872 |
+
include $this->plugin_path() . '/templates/repository-listing.php';
|
873 |
+
|
874 |
+
}
|
875 |
+
|
876 |
+
unset($site_key, $subscription_type, $expired, $upgrade_options, $products_avaliable);
|
877 |
+
|
878 |
+
}
|
879 |
+
|
880 |
+
}else{
|
881 |
+
|
882 |
+
echo '<center>' . __('No repositories defined.', 'installer') . '</center>';
|
883 |
+
|
884 |
+
}
|
885 |
+
|
886 |
+
if($screen->base == 'settings_page_installer'){ // settings page
|
887 |
+
echo '</div>';
|
888 |
+
}
|
889 |
+
|
890 |
+
|
891 |
+
}
|
892 |
+
|
893 |
+
public function get_product_price($repository_id, $package_id, $product_id, $incl_discount = false){
|
894 |
+
|
895 |
+
$price = false;
|
896 |
+
|
897 |
+
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package ){
|
898 |
+
|
899 |
+
if($package['id'] == $package_id){
|
900 |
+
if(isset($package['products'][$product_id])){
|
901 |
+
if($incl_discount && isset($package['products'][$product_id]['price_disc'])){
|
902 |
+
$price = $package['products'][$product_id]['price_disc'];
|
903 |
+
}elseif(isset($package['products'][$product_id]['price'])){
|
904 |
+
$price = $package['products'][$product_id]['price'];
|
905 |
+
}
|
906 |
+
}
|
907 |
+
break;
|
908 |
+
}
|
909 |
+
}
|
910 |
+
|
911 |
+
return $price;
|
912 |
+
}
|
913 |
+
|
914 |
+
private function _render_product_packages($packages, $subscription_type, $expired, $upgrade_options, $repository_id){
|
915 |
+
|
916 |
+
$data = array();
|
917 |
+
|
918 |
+
foreach($packages as $package_id => $package){
|
919 |
+
|
920 |
+
$row = array('products' => array(), 'downloads' => array());
|
921 |
+
foreach($package['products'] as $product){
|
922 |
+
|
923 |
+
// filter out free subscriptions from being displayed as buying options
|
924 |
+
if( empty($product['price']) && (empty($subscription_type) || $expired) ){
|
925 |
+
continue;
|
926 |
+
}
|
927 |
+
|
928 |
+
// buy base
|
929 |
+
if(empty($subscription_type) || $expired) {
|
930 |
+
|
931 |
+
$p['url'] = $this->append_parameters_to_buy_url($product['url'], $repository_id);
|
932 |
+
if (!empty($product['price_disc'])) {
|
933 |
+
$p['label'] = $product['call2action'] . ' - ' . sprintf('$%s %s$%d%s (USD)', $product['price_disc'], ' <del>', $product['price'], '</del>');
|
934 |
+
} else {
|
935 |
+
$p['label'] = $product['call2action'] . ' - ' . sprintf('$%d (USD)', $product['price']);
|
936 |
+
}
|
937 |
+
$row['products'][] = $p;
|
938 |
+
|
939 |
+
// renew
|
940 |
+
} elseif(isset($subscription_type) && $product['subscription_type'] == $subscription_type){
|
941 |
+
|
942 |
+
if($product['renewals']) {
|
943 |
+
foreach ($product['renewals'] as $renewal) {
|
944 |
+
$p['url'] = $this->append_parameters_to_buy_url($renewal['url'], $repository_id);
|
945 |
+
$p['label'] = $renewal['call2action'] . ' - ' . sprintf('$%d (USD)', $renewal['price']);
|
946 |
+
}
|
947 |
+
|
948 |
+
$row['products'][] = $p;
|
949 |
+
}
|
950 |
+
|
951 |
+
}
|
952 |
+
|
953 |
+
// upgrades
|
954 |
+
if(!empty($upgrade_options[$product['subscription_type']])){
|
955 |
+
|
956 |
+
foreach($upgrade_options[$product['subscription_type']] as $stype => $upgrade){
|
957 |
+
if($stype != $subscription_type) continue;
|
958 |
+
|
959 |
+
$p['url'] = $this->append_parameters_to_buy_url($upgrade['url'], $repository_id);
|
960 |
+
if (!empty($upgrade['price_disc'])) {
|
961 |
+
$p['label'] = $upgrade['call2action'] . ' - ' . sprintf('$%s %s$%d%s (USD)', $upgrade['price_disc'], ' <del>', $upgrade['price'], '</del>');
|
962 |
+
} else {
|
963 |
+
$p['label'] = $upgrade['call2action'] . ' - ' . sprintf('$%d (USD)', $upgrade['price']);
|
964 |
+
}
|
965 |
+
$row['products'][] = $p;
|
966 |
+
|
967 |
+
}
|
968 |
+
|
969 |
+
}
|
970 |
+
|
971 |
+
// downloads
|
972 |
+
if(isset($subscription_type) && !$expired && $product['subscription_type'] == $subscription_type){
|
973 |
+
foreach($product['plugins'] as $plugin_slug){
|
974 |
+
|
975 |
+
$row['downloads'][] = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
976 |
+
|
977 |
+
}
|
978 |
+
|
979 |
+
}
|
980 |
+
|
981 |
+
//subpackages
|
982 |
+
if(!empty($package['sub-packages'])){
|
983 |
+
$row['sub-packages'] = $package['sub-packages'];
|
984 |
+
}
|
985 |
+
|
986 |
+
}
|
987 |
+
|
988 |
+
$row['id'] = $package['id'];
|
989 |
+
$row['image_url'] = $package['image_url'];
|
990 |
+
$row['name'] = $package['name'];
|
991 |
+
$row['description'] = $package['description'];
|
992 |
+
|
993 |
+
if(!empty($row['products']) || !empty($row['downloads']) || !empty($row['sub-packages'])){
|
994 |
+
$data[] = $row;
|
995 |
+
}
|
996 |
+
|
997 |
+
|
998 |
+
}
|
999 |
+
|
1000 |
+
return $data;
|
1001 |
+
|
1002 |
+
}
|
1003 |
+
|
1004 |
+
public function get_extra_url_parameters(){
|
1005 |
+
|
1006 |
+
$parameters = array();
|
1007 |
+
|
1008 |
+
if(!empty($this->package_source)){
|
1009 |
+
foreach($this->package_source as $key => $val){
|
1010 |
+
$parameters[$key] = $val;
|
1011 |
+
}
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
$parameters['installer_version'] = WP_INSTALLER_VERSION;
|
1015 |
+
$parameters['theme'] = wp_get_theme()->get( 'Name' );
|
1016 |
+
$parameters['site_name'] = get_bloginfo( 'name' );
|
1017 |
+
|
1018 |
+
return $parameters;
|
1019 |
+
}
|
1020 |
+
|
1021 |
+
public function append_parameters_to_buy_url($url, $repository_id, $args = array()){
|
1022 |
+
|
1023 |
+
$url = add_query_arg( array('icl_site_url' => $this->get_installer_site_url( $repository_id ) ), $url );
|
1024 |
+
|
1025 |
+
$affiliate_id = false;
|
1026 |
+
$affiliate_key = false;
|
1027 |
+
|
1028 |
+
// Add extra parameters for custom Installer packages
|
1029 |
+
if( !empty($this->package_source) ){
|
1030 |
+
$extra = $this->get_extra_url_parameters();
|
1031 |
+
|
1032 |
+
if( !empty($extra['repository']) && $extra['repository'] == $repository_id ) {
|
1033 |
+
|
1034 |
+
if( !empty($extra['affiliate_key']) && !empty($extra['user_id']) ){
|
1035 |
+
$this->config['affiliate_id:' . $repository_id] = $extra['user_id'];
|
1036 |
+
$this->config['affiliate_key:' . $repository_id] = $extra['affiliate_key'];
|
1037 |
+
unset($extra['affiliate_key'], $extra['user_id'], $extra['repository']); // no need to include these ones
|
1038 |
+
}
|
1039 |
+
|
1040 |
+
$url = add_query_arg($extra, $url);
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
if(isset($this->config['affiliate_id:' . $repository_id]) && isset($this->config['affiliate_key:' . $repository_id])){
|
1046 |
+
|
1047 |
+
$affiliate_id = $this->config['affiliate_id:' . $repository_id];
|
1048 |
+
$affiliate_key = $this->config['affiliate_key:' . $repository_id];
|
1049 |
+
|
1050 |
+
}elseif(isset($args['affiliate_id:' . $repository_id]) && isset($args['affiliate_key:' . $repository_id])){
|
1051 |
+
|
1052 |
+
$affiliate_id = $args['affiliate_id:' . $repository_id];
|
1053 |
+
$affiliate_key = $args['affiliate_key:' . $repository_id];
|
1054 |
+
|
1055 |
+
}elseif(defined('ICL_AFFILIATE_ID') && defined('ICL_AFFILIATE_KEY')){ //support for 1 repo
|
1056 |
+
|
1057 |
+
$affiliate_id = ICL_AFFILIATE_ID;
|
1058 |
+
$affiliate_key = ICL_AFFILIATE_KEY;
|
1059 |
+
|
1060 |
+
}elseif(isset($this->config['affiliate_id']) && isset($this->config['affiliate_key'])) {
|
1061 |
+
// BACKWARDS COMPATIBILITY
|
1062 |
+
$affiliate_id = $this->config['affiliate_id'];
|
1063 |
+
$affiliate_key = $this->config['affiliate_key'];
|
1064 |
+
}
|
1065 |
+
|
1066 |
+
if($affiliate_id && $affiliate_key){
|
1067 |
+
$url = add_query_arg(array('aid' => $affiliate_id, 'affiliate_key' => $affiliate_key), $url);
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
if($repository_id == 'wpml'){
|
1071 |
+
$url = add_query_arg(array('using_icl' => $this->_using_icl, 'wpml_version' => $this->_wpml_version), $url);
|
1072 |
+
}
|
1073 |
+
|
1074 |
+
$url = apply_filters('wp_installer_buy_url', $url);
|
1075 |
+
|
1076 |
+
$url = esc_url($url);
|
1077 |
+
|
1078 |
+
return $url;
|
1079 |
+
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
public function save_site_key($args = array()){
|
1083 |
+
|
1084 |
+
$error = '';
|
1085 |
+
|
1086 |
+
if( isset( $args['repository_id'] ) ){
|
1087 |
+
$repository_id = $args['repository_id'];
|
1088 |
+
}elseif( isset( $_POST['repository_id'] ) ){
|
1089 |
+
$repository_id = sanitize_text_field( $_POST['repository_id'] );
|
1090 |
+
}else{
|
1091 |
+
$repository_id = false;
|
1092 |
+
}
|
1093 |
+
|
1094 |
+
if( isset( $args['nonce'] ) ){
|
1095 |
+
$nonce = $args['nonce'];
|
1096 |
+
}elseif( isset($_POST['nonce'] ) ){
|
1097 |
+
$nonce = sanitize_text_field( $_POST['nonce'] );
|
1098 |
+
}else{
|
1099 |
+
$nonce = '';
|
1100 |
+
}
|
1101 |
+
|
1102 |
+
if( isset( $args['site_key'] ) ){
|
1103 |
+
$site_key = $args['site_key'];
|
1104 |
+
} else {
|
1105 |
+
$site_key = sanitize_text_field( $_POST[ 'site_key_' . $repository_id] );
|
1106 |
+
}
|
1107 |
+
$site_key = preg_replace("/[^A-Za-z0-9]/", '', $site_key);
|
1108 |
+
|
1109 |
+
if($repository_id && $nonce && wp_create_nonce('save_site_key_' . $repository_id) == $nonce){
|
1110 |
+
|
1111 |
+
try {
|
1112 |
+
$subscription_data = $this->fetch_subscription_data( $repository_id, $site_key, self::SITE_KEY_VALIDATION_SOURCE_REGISTRATION );
|
1113 |
+
|
1114 |
+
if ( $subscription_data ) {
|
1115 |
+
$this->settings['repositories'][$repository_id]['subscription'] = array('key' => $site_key, 'data' => $subscription_data);
|
1116 |
+
$this->save_settings();
|
1117 |
+
} else {
|
1118 |
+
$error = __( 'Invalid site key for the current site.', 'installer' )
|
1119 |
+
. '<br /><div class="installer-footnote">' . __('Please note that the site key is case sensitive.', 'installer') . '</div>';
|
1120 |
+
}
|
1121 |
+
|
1122 |
+
} catch (Exception $e ){
|
1123 |
+
$error = $e->getMessage();
|
1124 |
+
if( preg_match('#Could not resolve host: (.*)#', $error, $matches) || preg_match('#Couldn\'t resolve host \'(.*)\'#', $error, $matches) ){
|
1125 |
+
$error = sprintf(__("%s cannot access %s to register. Try again to see if it's a temporary problem. If the problem continues, make sure that this site has access to the Internet. You can still use the plugin without registration, but you will not receive automated updates.", 'installer'),
|
1126 |
+
'<strong><i>' . $this->get_generic_product_name($repository_id) . '</i></strong>',
|
1127 |
+
'<strong><i>' . $matches[1]. '</i></strong>'
|
1128 |
+
) ;
|
1129 |
+
}
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
}
|
1133 |
+
|
1134 |
+
$return = array('error' => $error);
|
1135 |
+
|
1136 |
+
if($this->api_debug){
|
1137 |
+
$return['debug'] = $this->api_debug;
|
1138 |
+
}
|
1139 |
+
|
1140 |
+
if(!empty($args['return'])){
|
1141 |
+
return $return;
|
1142 |
+
}else{
|
1143 |
+
echo json_encode($return);
|
1144 |
+
exit;
|
1145 |
+
}
|
1146 |
+
|
1147 |
+
}
|
1148 |
+
|
1149 |
+
/**
|
1150 |
+
* Alias for WP_Installer::get_repository_site_key
|
1151 |
+
* @see WP_Installer::get_repository_site_key()
|
1152 |
+
*
|
1153 |
+
* @param string $repository_id
|
1154 |
+
* @return string (site key) or bool
|
1155 |
+
*/
|
1156 |
+
public function get_site_key($repository_id){
|
1157 |
+
return WP_Installer::get_repository_site_key( $repository_id );
|
1158 |
+
}
|
1159 |
+
|
1160 |
+
public function remove_site_key( $repository_id ){
|
1161 |
+
if( isset( $this->settings['repositories'][$repository_id] ) ){
|
1162 |
+
unset($this->settings['repositories'][$repository_id]['subscription']);
|
1163 |
+
$this->save_settings();
|
1164 |
+
$this->refresh_repositories_data();
|
1165 |
+
}
|
1166 |
+
}
|
1167 |
+
|
1168 |
+
public function remove_site_key_ajax(){
|
1169 |
+
if($_POST['nonce'] == wp_create_nonce('remove_site_key_' . $_POST['repository_id'])){
|
1170 |
+
$this->remove_site_key( $_POST['repository_id'] );
|
1171 |
+
}
|
1172 |
+
exit;
|
1173 |
+
}
|
1174 |
+
|
1175 |
+
public function validate_repository_subscription(){
|
1176 |
+
$repository_id = isset($_GET['validate_repository']) ? sanitize_text_field( $_GET['validate_repository'] ) : false;
|
1177 |
+
if($repository_id){
|
1178 |
+
|
1179 |
+
$site_key = $this->get_site_key($repository_id);
|
1180 |
+
if($site_key) {
|
1181 |
+
$subscription_data = $this->fetch_subscription_data( $repository_id, $site_key, self::SITE_KEY_VALIDATION_SOURCE_REVALIDATION);
|
1182 |
+
if(empty($subscription_data)){
|
1183 |
+
unset($this->settings['repositories'][$repository_id]['subscription']);
|
1184 |
+
delete_site_transient('update_plugins');
|
1185 |
+
$this->save_settings();
|
1186 |
+
}
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
wp_redirect($this->menu_url() . '#repository-' . $repository_id);
|
1190 |
+
exit;
|
1191 |
+
|
1192 |
+
}
|
1193 |
+
|
1194 |
+
}
|
1195 |
+
|
1196 |
+
public function update_site_key(){
|
1197 |
+
|
1198 |
+
$error = '';
|
1199 |
+
|
1200 |
+
$repository_id = sanitize_text_field ( $_POST['repository_id'] );
|
1201 |
+
if($_POST['nonce'] == wp_create_nonce('update_site_key_' . $repository_id )){
|
1202 |
+
|
1203 |
+
$site_key = $this->get_site_key($_POST['repository_id']);
|
1204 |
+
|
1205 |
+
if($site_key){
|
1206 |
+
try {
|
1207 |
+
$subscription_data = $this->fetch_subscription_data( $repository_id, $site_key, self::SITE_KEY_VALIDATION_SOURCE_UPDATES_CHECK );
|
1208 |
+
|
1209 |
+
if ( $subscription_data ) {
|
1210 |
+
$this->settings['repositories'][$repository_id]['subscription'] = array('key' => $site_key, 'data' => $subscription_data);
|
1211 |
+
|
1212 |
+
//also refresh products information
|
1213 |
+
$this->refresh_repositories_data();
|
1214 |
+
|
1215 |
+
$this->save_settings();
|
1216 |
+
|
1217 |
+
} else {
|
1218 |
+
unset($this->settings['repositories'][$repository_id]['subscription']);
|
1219 |
+
$error = __( 'Invalid site key for the current site. If the error persists, try to unregister first and then register again with the same site key.', 'installer' );
|
1220 |
+
}
|
1221 |
+
|
1222 |
+
|
1223 |
+
} catch (Exception $e ){
|
1224 |
+
$error = $e->getMessage();
|
1225 |
+
if( preg_match('#Could not resolve host: (.*)#', $error, $matches) || preg_match('#Couldn\'t resolve host \'(.*)\'#', $error, $matches) ){
|
1226 |
+
$error = sprintf(__("%s cannot access %s to register. Try again to see if it's a temporary problem. If the problem continues, make sure that this site has access to the Internet. You can still use the plugin without registration, but you will not receive automated updates.", 'installer'),
|
1227 |
+
'<strong><i>' . $this->get_generic_product_name($repository_id) . '</i></strong>',
|
1228 |
+
'<strong><i>' . $matches[1]. '</i></strong>'
|
1229 |
+
) ;
|
1230 |
+
}
|
1231 |
+
}
|
1232 |
+
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
}
|
1236 |
+
|
1237 |
+
echo json_encode(array('error' => $error));
|
1238 |
+
|
1239 |
+
exit;
|
1240 |
+
}
|
1241 |
+
|
1242 |
+
public function api_debug_log($text){
|
1243 |
+
|
1244 |
+
if(defined('WPML_DEBUG_INSTALLER') && WPML_DEBUG_INSTALLER){
|
1245 |
+
|
1246 |
+
if(!is_scalar($text)){
|
1247 |
+
$text = print_r($text, 1);
|
1248 |
+
}
|
1249 |
+
|
1250 |
+
$this->api_debug .= $text . "\n";
|
1251 |
+
|
1252 |
+
}
|
1253 |
+
|
1254 |
+
}
|
1255 |
+
|
1256 |
+
public function fetch_subscription_data( $repository_id, $site_key, $source = self::SITE_KEY_VALIDATION_SOURCE_OTHER ){
|
1257 |
+
|
1258 |
+
$subscription_data = false;
|
1259 |
+
|
1260 |
+
$args['body'] = array(
|
1261 |
+
'action' => 'site_key_validation',
|
1262 |
+
'site_key' => $site_key,
|
1263 |
+
'site_url' => $this->get_installer_site_url( $repository_id ),
|
1264 |
+
'source' => $source
|
1265 |
+
);
|
1266 |
+
|
1267 |
+
if($repository_id == 'wpml'){
|
1268 |
+
$args['body']['using_icl'] = $this->_using_icl;
|
1269 |
+
$args['body']['wpml_version'] = $this->_wpml_version;
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
$args['body']['installer_version'] = WP_INSTALLER_VERSION;
|
1273 |
+
$args['body']['theme'] = wp_get_theme()->get( 'Name' );
|
1274 |
+
$args['body']['site_name'] = get_bloginfo( 'name' );
|
1275 |
+
|
1276 |
+
$args['body']['versions'] = $this->get_local_product_versions( $repository_id );
|
1277 |
+
|
1278 |
+
$args['timeout'] = 45;
|
1279 |
+
|
1280 |
+
// Add extra parameters for custom Installer packages
|
1281 |
+
if( !empty($this->package_source) ){
|
1282 |
+
$extra = $this->get_extra_url_parameters();
|
1283 |
+
if( !empty($extra['repository']) && $extra['repository'] == $repository_id ) {
|
1284 |
+
unset($extra['repository']);
|
1285 |
+
foreach($extra as $key => $val){
|
1286 |
+
$args['body'][$key] = $val;
|
1287 |
+
}
|
1288 |
+
}
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
$response = wp_remote_post($this->repositories[$repository_id]['api-url'], $args);
|
1292 |
+
|
1293 |
+
$this->api_debug_log("POST {$this->repositories[$repository_id]['api-url']}");
|
1294 |
+
$this->api_debug_log($args);
|
1295 |
+
|
1296 |
+
$this->log("POST {$this->repositories[$repository_id]['api-url']} - fetch subscription data");
|
1297 |
+
|
1298 |
+
if( !is_wp_error($response) ){
|
1299 |
+
$datas = wp_remote_retrieve_body($response);
|
1300 |
+
|
1301 |
+
if(is_serialized($datas)){
|
1302 |
+
$data = unserialize($datas);
|
1303 |
+
$this->api_debug_log($data);
|
1304 |
+
|
1305 |
+
if( !empty( $data->subscription_data ) ){
|
1306 |
+
$subscription_data = $data->subscription_data;
|
1307 |
+
}
|
1308 |
+
|
1309 |
+
do_action( 'installer_fetched_subscription_data', $data, $repository_id);
|
1310 |
+
|
1311 |
+
}else{
|
1312 |
+
$this->api_debug_log($datas);
|
1313 |
+
}
|
1314 |
+
|
1315 |
+
}else{
|
1316 |
+
|
1317 |
+
$this->api_debug_log($response);
|
1318 |
+
throw new Exception( $response->get_error_message() );
|
1319 |
+
}
|
1320 |
+
|
1321 |
+
return $subscription_data;
|
1322 |
+
|
1323 |
+
}
|
1324 |
+
|
1325 |
+
function get_local_product_versions( $repository_id ){
|
1326 |
+
|
1327 |
+
$versions = array();
|
1328 |
+
|
1329 |
+
foreach( $this->settings['repositories'][$repository_id]['data']['packages'] as $package_id => $package ){
|
1330 |
+
|
1331 |
+
foreach( $package['products'] as $product_id => $product ){
|
1332 |
+
|
1333 |
+
foreach( $product['plugins'] as $plugin_slug ){
|
1334 |
+
|
1335 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
1336 |
+
|
1337 |
+
if( empty( $versions[$download['slug']] ) ) {
|
1338 |
+
$v = $this->get_plugin_installed_version($download['name'], $download['slug']);
|
1339 |
+
if($v){
|
1340 |
+
$versions[$download['slug']] = $v;
|
1341 |
+
}
|
1342 |
+
}
|
1343 |
+
|
1344 |
+
}
|
1345 |
+
|
1346 |
+
}
|
1347 |
+
|
1348 |
+
}
|
1349 |
+
|
1350 |
+
return $versions;
|
1351 |
+
}
|
1352 |
+
|
1353 |
+
public function get_repository_site_key($repository_id){
|
1354 |
+
$site_key = false;
|
1355 |
+
|
1356 |
+
if(!empty($this->settings['repositories'][$repository_id]['subscription']['key'])){
|
1357 |
+
$site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
|
1358 |
+
}
|
1359 |
+
|
1360 |
+
return $site_key;
|
1361 |
+
}
|
1362 |
+
|
1363 |
+
public function repository_has_valid_subscription($repository_id){
|
1364 |
+
|
1365 |
+
$valid = false;
|
1366 |
+
|
1367 |
+
if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
|
1368 |
+
|
1369 |
+
$subscription = $this->settings['repositories'][$repository_id]['subscription']['data'];
|
1370 |
+
$valid = ( $subscription->status == 1 && (strtotime($subscription->expires) > time() || empty($subscription->expires)) ) || $subscription->status == 4;
|
1371 |
+
|
1372 |
+
}
|
1373 |
+
return $valid;
|
1374 |
+
|
1375 |
+
}
|
1376 |
+
|
1377 |
+
public function repository_has_subscription($repository_id){
|
1378 |
+
$key = false;
|
1379 |
+
if(!empty($this->settings['repositories'][$repository_id]['subscription']['key'])){
|
1380 |
+
$key = $this->settings['repositories'][$repository_id]['subscription']['key'];
|
1381 |
+
}
|
1382 |
+
|
1383 |
+
return $key;
|
1384 |
+
|
1385 |
+
}
|
1386 |
+
|
1387 |
+
public function repository_has_expired_subscription($repository_id){
|
1388 |
+
|
1389 |
+
return $this->repository_has_subscription($repository_id) && !$this->repository_has_valid_subscription($repository_id);
|
1390 |
+
|
1391 |
+
}
|
1392 |
+
|
1393 |
+
public function get_generic_product_name($repository_id){
|
1394 |
+
|
1395 |
+
return $this->settings['repositories'][$repository_id]['data']['product-name'];
|
1396 |
+
|
1397 |
+
}
|
1398 |
+
|
1399 |
+
public function show_subscription_renew_warning($repository_id, $subscription_id){
|
1400 |
+
|
1401 |
+
$show = false;
|
1402 |
+
|
1403 |
+
$data = $this->settings['repositories'][$repository_id]['data'];
|
1404 |
+
if(!empty($data['subscriptions_meta'])){
|
1405 |
+
if(isset($data['subscriptions_meta']['expiration'])){
|
1406 |
+
|
1407 |
+
if(!empty($data['subscriptions_meta']['expiration'][$subscription_id])){
|
1408 |
+
|
1409 |
+
$days = $data['subscriptions_meta']['expiration'][$subscription_id]['days_warning'];
|
1410 |
+
$message = $data['subscriptions_meta']['expiration'][$subscription_id]['warning_message'];
|
1411 |
+
|
1412 |
+
}else{
|
1413 |
+
|
1414 |
+
//defaults
|
1415 |
+
$days = 30;
|
1416 |
+
$message = __('You will have to renew your subscription in order to continue getting the updates and support.', 'installer');
|
1417 |
+
|
1418 |
+
}
|
1419 |
+
|
1420 |
+
if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
|
1421 |
+
$subscription = $this->settings['repositories'][$repository_id]['subscription'];
|
1422 |
+
|
1423 |
+
if($subscription['data']->subscription_type == $subscription_id && !empty($subscription['data']->expires)){
|
1424 |
+
|
1425 |
+
if(strtotime($subscription['data']->expires) < strtotime(sprintf("+%d day", $days))){
|
1426 |
+
|
1427 |
+
$days_to_expiration = ceil((strtotime($subscription['data']->expires) - time()) / 86400);
|
1428 |
+
|
1429 |
+
echo '<div><p class="installer-warn-box">' .
|
1430 |
+
sprintf(_n('Your subscription expires in %d day.', 'Your subscription expires in %d days.', $days_to_expiration, 'installer'), $days_to_expiration) .
|
1431 |
+
'<br />' . $message .
|
1432 |
+
'</p></div>';
|
1433 |
+
|
1434 |
+
$show = true;
|
1435 |
+
|
1436 |
+
}
|
1437 |
+
|
1438 |
+
}
|
1439 |
+
|
1440 |
+
}
|
1441 |
+
|
1442 |
+
|
1443 |
+
}
|
1444 |
+
}
|
1445 |
+
|
1446 |
+
|
1447 |
+
return $show;
|
1448 |
+
|
1449 |
+
}
|
1450 |
+
|
1451 |
+
public function setup_plugins_renew_warnings(){
|
1452 |
+
|
1453 |
+
$plugins = get_plugins();
|
1454 |
+
|
1455 |
+
$subscriptions_with_warnings = array();
|
1456 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
1457 |
+
|
1458 |
+
if($this->repository_has_valid_subscription($repository_id)){
|
1459 |
+
$subscription_type = $this->settings['repositories'][$repository_id]['subscription']['data']->subscription_type;
|
1460 |
+
$expires = $this->settings['repositories'][$repository_id]['subscription']['data']->expires;
|
1461 |
+
|
1462 |
+
$never_expires = isset($this->settings['repositories'][$repository_id]['subscription'])
|
1463 |
+
&& empty($this->settings['repositories'][$repository_id]['subscription']['data']->expires)
|
1464 |
+
&& (
|
1465 |
+
$this->settings['repositories'][$repository_id]['subscription']['data']->status == 4 ||
|
1466 |
+
$this->settings['repositories'][$repository_id]['subscription']['data']->status == 1
|
1467 |
+
);
|
1468 |
+
|
1469 |
+
if(!$never_expires){
|
1470 |
+
if(isset($this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type])){
|
1471 |
+
|
1472 |
+
$days_warning = $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type]['days_warning'];
|
1473 |
+
$custom_message = $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type]['warning_message'];
|
1474 |
+
|
1475 |
+
}else{
|
1476 |
+
//defaults
|
1477 |
+
$days_warning = 30;
|
1478 |
+
$custom_message = __('You will have to renew your subscription in order to continue getting the updates and support.', 'installer');
|
1479 |
+
}
|
1480 |
+
|
1481 |
+
if(strtotime($expires) < strtotime(sprintf('+%d day', $days_warning)) ){
|
1482 |
+
|
1483 |
+
$days_to_expiration = ceil((strtotime($expires) - time()) / 86400);
|
1484 |
+
|
1485 |
+
$message = sprintf(_n('Your subscription expires in %d day.', 'Your subscription expires in %d days.', $days_to_expiration, 'installer'), $days_to_expiration);
|
1486 |
+
$subscriptions_with_warnings[$subscription_type] = $message . ' ' . $custom_message;
|
1487 |
+
|
1488 |
+
}
|
1489 |
+
}
|
1490 |
+
|
1491 |
+
}
|
1492 |
+
|
1493 |
+
}
|
1494 |
+
|
1495 |
+
|
1496 |
+
|
1497 |
+
foreach($plugins as $plugin_id => $plugin){
|
1498 |
+
|
1499 |
+
$slug = dirname($plugin_id);
|
1500 |
+
if(empty($slug)) continue;
|
1501 |
+
|
1502 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
1503 |
+
|
1504 |
+
if($this->repository_has_valid_subscription($repository_id)){
|
1505 |
+
|
1506 |
+
foreach($repository['data']['packages'] as $package){
|
1507 |
+
|
1508 |
+
foreach($package['products'] as $product){
|
1509 |
+
|
1510 |
+
foreach($product['plugins'] as $plugin_slug){
|
1511 |
+
|
1512 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
1513 |
+
|
1514 |
+
if($download['slug'] == $slug || $download['name'] == $plugin['Name'] || $download['name'] == $plugin['Title']){ //match order: slug, name, title
|
1515 |
+
|
1516 |
+
if(isset($subscriptions_with_warnings[$product['subscription_type']])){
|
1517 |
+
|
1518 |
+
$this->_plugins_renew_warnings[$plugin_id] = $subscriptions_with_warnings[$product['subscription_type']];
|
1519 |
+
|
1520 |
+
}
|
1521 |
+
|
1522 |
+
}
|
1523 |
+
|
1524 |
+
}
|
1525 |
+
|
1526 |
+
}
|
1527 |
+
|
1528 |
+
}
|
1529 |
+
|
1530 |
+
}
|
1531 |
+
|
1532 |
+
}
|
1533 |
+
|
1534 |
+
}
|
1535 |
+
|
1536 |
+
}
|
1537 |
+
|
1538 |
+
public function queue_plugins_renew_warnings() {
|
1539 |
+
|
1540 |
+
if(!empty($this->_plugins_renew_warnings)){
|
1541 |
+
|
1542 |
+
foreach($this->_plugins_renew_warnings as $plugin_id => $message){
|
1543 |
+
|
1544 |
+
add_action( "after_plugin_row_" . $plugin_id, array($this, 'plugins_renew_warning'), 10, 3 );
|
1545 |
+
}
|
1546 |
+
|
1547 |
+
}
|
1548 |
+
|
1549 |
+
}
|
1550 |
+
|
1551 |
+
public function plugins_renew_warning($plugin_file, $plugin_data, $status){
|
1552 |
+
|
1553 |
+
if(empty($this->_plugins_renew_warnings[$plugin_file])) return;
|
1554 |
+
|
1555 |
+
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
|
1556 |
+
?>
|
1557 |
+
|
1558 |
+
<tr class="plugin-update-tr"><td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="plugin-update colspanchange">
|
1559 |
+
<div class="update-message">
|
1560 |
+
<?php
|
1561 |
+
echo $this->_plugins_renew_warnings[$plugin_file]. ' ';
|
1562 |
+
printf(__('%sRenew here%s.', 'installer'),
|
1563 |
+
'<a href="' . $this->menu_url() . '">', '</a>');
|
1564 |
+
?>
|
1565 |
+
</div>
|
1566 |
+
</tr>
|
1567 |
+
|
1568 |
+
<?php
|
1569 |
+
|
1570 |
+
}
|
1571 |
+
|
1572 |
+
public function get_subscription_type_for_repository($repository_id){
|
1573 |
+
|
1574 |
+
$subscription_type = false;
|
1575 |
+
|
1576 |
+
if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
|
1577 |
+
$subscription_type = $this->settings['repositories'][$repository_id]['subscription']['data']->subscription_type;
|
1578 |
+
}
|
1579 |
+
|
1580 |
+
return $subscription_type;
|
1581 |
+
|
1582 |
+
}
|
1583 |
+
|
1584 |
+
public function have_superior_subscription($subscription_type, $product){
|
1585 |
+
|
1586 |
+
$have = false;
|
1587 |
+
|
1588 |
+
if(is_array($product['upgrades'])){
|
1589 |
+
foreach($product['upgrades'] as $u){
|
1590 |
+
if($u['subscription_type'] == $subscription_type){
|
1591 |
+
$have = true;
|
1592 |
+
break;
|
1593 |
+
}
|
1594 |
+
}
|
1595 |
+
}
|
1596 |
+
|
1597 |
+
return $have;
|
1598 |
+
}
|
1599 |
+
|
1600 |
+
public function is_product_available_for_download($product_name, $repository_id){
|
1601 |
+
|
1602 |
+
$available = false;
|
1603 |
+
|
1604 |
+
$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
1605 |
+
$expired = $this->repository_has_expired_subscription($repository_id);
|
1606 |
+
|
1607 |
+
if($this->repository_has_subscription($repository_id) && !$expired){
|
1608 |
+
|
1609 |
+
$this->set_hierarchy_and_order();
|
1610 |
+
|
1611 |
+
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package_id => $package){
|
1612 |
+
|
1613 |
+
$has_top_package = false;
|
1614 |
+
|
1615 |
+
foreach($package['products'] as $product){
|
1616 |
+
|
1617 |
+
if($subscription_type == $product['subscription_type']){
|
1618 |
+
$has_top_package = true;
|
1619 |
+
if($product['name'] == $product_name){
|
1620 |
+
return $available = true;
|
1621 |
+
}
|
1622 |
+
}
|
1623 |
+
|
1624 |
+
}
|
1625 |
+
|
1626 |
+
if(!empty($package['sub-packages'])){
|
1627 |
+
foreach($package['sub-packages'] as $sub_package){
|
1628 |
+
foreach($sub_package['products'] as $product){
|
1629 |
+
if($product['name'] == $product_name && ($subscription_type == $product['subscription_type'] || $has_top_package)){
|
1630 |
+
return $available = true;
|
1631 |
+
}
|
1632 |
+
}
|
1633 |
+
}
|
1634 |
+
}
|
1635 |
+
|
1636 |
+
}
|
1637 |
+
}
|
1638 |
+
|
1639 |
+
return $available;
|
1640 |
+
|
1641 |
+
}
|
1642 |
+
|
1643 |
+
public function get_upgrade_options($repository_id){
|
1644 |
+
$all_upgrades = array();
|
1645 |
+
|
1646 |
+
|
1647 |
+
//get all products: packages and subpackages
|
1648 |
+
$all_products = array();
|
1649 |
+
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
|
1650 |
+
foreach($package['products'] as $product) {
|
1651 |
+
$all_products[] = $product;
|
1652 |
+
}
|
1653 |
+
if(!empty($package['sub-packages'])){
|
1654 |
+
foreach($package['sub-packages'] as $subpackage){
|
1655 |
+
foreach($subpackage['products'] as $product) {
|
1656 |
+
$all_products[] = $product;
|
1657 |
+
}
|
1658 |
+
|
1659 |
+
}
|
1660 |
+
|
1661 |
+
}
|
1662 |
+
|
1663 |
+
}
|
1664 |
+
|
1665 |
+
foreach( $all_products as $product ) {
|
1666 |
+
if ($product['upgrades']) {
|
1667 |
+
foreach ($product['upgrades'] as $upgrade) {
|
1668 |
+
if ($this->repository_has_valid_subscription($repository_id) || ($this->repository_has_subscription($repository_id) && $upgrade['including_expired'])) {
|
1669 |
+
$all_upgrades[$upgrade['subscription_type']][$product['subscription_type']] = $upgrade;
|
1670 |
+
}
|
1671 |
+
}
|
1672 |
+
}
|
1673 |
+
}
|
1674 |
+
|
1675 |
+
return $all_upgrades;
|
1676 |
+
|
1677 |
+
}
|
1678 |
+
|
1679 |
+
public function append_site_key_to_download_url($url, $key, $repository_id){
|
1680 |
+
|
1681 |
+
$url_params['site_key'] = $key;
|
1682 |
+
$url_params['site_url'] = $this->get_installer_site_url( $repository_id );
|
1683 |
+
|
1684 |
+
|
1685 |
+
// Add extra parameters for custom Installer packages
|
1686 |
+
if( !empty($this->package_source) ){
|
1687 |
+
$extra = $this->get_extra_url_parameters();
|
1688 |
+
if( !empty($extra['repository']) && $extra['repository'] == $repository_id ) {
|
1689 |
+
unset($extra['repository']);
|
1690 |
+
foreach($extra as $key => $val){
|
1691 |
+
$url_params[$key] = $val;
|
1692 |
+
}
|
1693 |
+
}
|
1694 |
+
}
|
1695 |
+
|
1696 |
+
$url = add_query_arg($url_params, $url);
|
1697 |
+
|
1698 |
+
if($repository_id == 'wpml'){
|
1699 |
+
$url = add_query_arg(array('using_icl' => $this->_using_icl, 'wpml_version' => $this->_wpml_version), $url);
|
1700 |
+
}
|
1701 |
+
|
1702 |
+
return $url;
|
1703 |
+
|
1704 |
+
}
|
1705 |
+
|
1706 |
+
public function plugin_is_installed($name, $slug, $version = null){
|
1707 |
+
|
1708 |
+
$is = false;
|
1709 |
+
|
1710 |
+
$plugins = get_plugins();
|
1711 |
+
|
1712 |
+
foreach($plugins as $plugin_id => $plugin){
|
1713 |
+
|
1714 |
+
$wp_plugin_slug = dirname($plugin_id);
|
1715 |
+
|
1716 |
+
// Exception: embedded plugins
|
1717 |
+
if( $wp_plugin_slug == $slug || $plugin['Name'] == $name || $plugin['Title'] == $name || ( $wp_plugin_slug == $slug . '-embedded' || $plugin['Name'] == $name . ' Embedded' ) ){
|
1718 |
+
if($version){
|
1719 |
+
if(version_compare($plugin['Version'], $version, '>=')){
|
1720 |
+
$is = $plugin['Version'];
|
1721 |
+
}
|
1722 |
+
}else{
|
1723 |
+
$is = $plugin['Version'];
|
1724 |
+
}
|
1725 |
+
|
1726 |
+
break;
|
1727 |
+
}
|
1728 |
+
|
1729 |
+
}
|
1730 |
+
|
1731 |
+
//exception: Types name difference
|
1732 |
+
if(!$is && $name == 'Types'){
|
1733 |
+
return $this->plugin_is_installed('Types - Complete Solution for Custom Fields and Types', $slug, $version);
|
1734 |
+
}
|
1735 |
+
|
1736 |
+
return $is;
|
1737 |
+
}
|
1738 |
+
|
1739 |
+
public function plugin_is_embedded_version($name, $slug){
|
1740 |
+
$is = false;
|
1741 |
+
|
1742 |
+
$plugins = get_plugins();
|
1743 |
+
|
1744 |
+
//false if teh full version is also installed
|
1745 |
+
$is_full_installed = false;
|
1746 |
+
foreach($plugins as $plugin_id => $plugin){
|
1747 |
+
|
1748 |
+
if(($plugin['Name'] == $name && !preg_match("#-embedded$#", $slug)) ){
|
1749 |
+
$is_full_installed = true;
|
1750 |
+
break;
|
1751 |
+
}
|
1752 |
+
|
1753 |
+
}
|
1754 |
+
|
1755 |
+
if($is_full_installed){
|
1756 |
+
return false;
|
1757 |
+
}
|
1758 |
+
|
1759 |
+
foreach($plugins as $plugin_id => $plugin){
|
1760 |
+
|
1761 |
+
// TBD
|
1762 |
+
$wp_plugin_slug = dirname($plugin_id);
|
1763 |
+
if( $wp_plugin_slug == $slug . '-embedded' && $plugin['Name'] == $name . ' Embedded'){
|
1764 |
+
$is = true;
|
1765 |
+
break;
|
1766 |
+
}
|
1767 |
+
|
1768 |
+
}
|
1769 |
+
|
1770 |
+
return $is;
|
1771 |
+
|
1772 |
+
}
|
1773 |
+
|
1774 |
+
//Alias for plugin_is_installed
|
1775 |
+
public function get_plugin_installed_version($name, $slug){
|
1776 |
+
|
1777 |
+
return $this->plugin_is_installed($name, $slug);
|
1778 |
+
|
1779 |
+
}
|
1780 |
+
|
1781 |
+
public function get_plugin_repository_version($repository_id, $slug){
|
1782 |
+
$version = false;
|
1783 |
+
|
1784 |
+
if(!empty($this->settings['repositories'][$repository_id]['data']['packages'])){
|
1785 |
+
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
|
1786 |
+
foreach($package['products'] as $product) {
|
1787 |
+
|
1788 |
+
foreach($product['plugins'] as $plugin_slug){
|
1789 |
+
|
1790 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
1791 |
+
|
1792 |
+
if($download['slug'] == $slug){
|
1793 |
+
$version = $download['version'];
|
1794 |
+
break (3);
|
1795 |
+
}
|
1796 |
+
|
1797 |
+
}
|
1798 |
+
|
1799 |
+
}
|
1800 |
+
}
|
1801 |
+
}
|
1802 |
+
|
1803 |
+
return $version;
|
1804 |
+
}
|
1805 |
+
|
1806 |
+
public function is_uploading_allowed(){
|
1807 |
+
|
1808 |
+
//_deprecated_function ( __FUNCTION__, '1.7.3', 'Installer_Dependencies::' . __FUNCTION__ );
|
1809 |
+
return $this->dependencies->is_uploading_allowed();
|
1810 |
+
|
1811 |
+
}
|
1812 |
+
|
1813 |
+
public function download_plugin_ajax_handler(){
|
1814 |
+
|
1815 |
+
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
1816 |
+
require_once $this->plugin_path() . '/includes/installer-upgrader-skins.php';
|
1817 |
+
|
1818 |
+
$data = json_decode( base64_decode( sanitize_text_field ( $_POST['data'] ) ), true );
|
1819 |
+
|
1820 |
+
$ret = false;
|
1821 |
+
$plugin_id = false;
|
1822 |
+
$message = '';
|
1823 |
+
|
1824 |
+
//validate subscription
|
1825 |
+
$site_key = $this->get_repository_site_key($data['repository_id']);
|
1826 |
+
$subscription_data = $this->fetch_subscription_data( $data['repository_id'], $site_key , self::SITE_KEY_VALIDATION_SOURCE_DOWNLOAD_REPORT);
|
1827 |
+
|
1828 |
+
if($subscription_data && !is_wp_error($subscription_data) && $this->repository_has_valid_subscription($data['repository_id'])){
|
1829 |
+
|
1830 |
+
if($data['nonce'] == wp_create_nonce('install_plugin_' . $data['url'])){
|
1831 |
+
|
1832 |
+
$upgrader_skins = new Installer_Upgrader_Skins(); //use our custom (mute) Skin
|
1833 |
+
$upgrader = new Plugin_Upgrader($upgrader_skins);
|
1834 |
+
|
1835 |
+
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
|
1836 |
+
|
1837 |
+
$plugins = get_plugins();
|
1838 |
+
|
1839 |
+
//upgrade or install?
|
1840 |
+
foreach($plugins as $id => $plugin){
|
1841 |
+
$wp_plugin_slug = dirname($id);
|
1842 |
+
$is_embedded = $this->plugin_is_embedded_version(preg_replace('/ Embedded$/', '', $plugin['Name']), preg_replace('/-embedded$/', '', $wp_plugin_slug));
|
1843 |
+
|
1844 |
+
if($wp_plugin_slug == $data['slug'] || $is_embedded && preg_replace('/-embedded$/', '', $wp_plugin_slug) == $data['slug']){
|
1845 |
+
$plugin_id = $id;
|
1846 |
+
break;
|
1847 |
+
}
|
1848 |
+
}
|
1849 |
+
|
1850 |
+
if($plugin_id && empty($is_embedded)){ //upgrade
|
1851 |
+
$response['upgrade'] = 1;
|
1852 |
+
|
1853 |
+
$plugin_is_active = is_plugin_active($plugin_id);
|
1854 |
+
|
1855 |
+
$ret = $upgrader->upgrade($plugin_id);
|
1856 |
+
|
1857 |
+
if(!$ret && !empty($upgrader->skin->installer_error)){
|
1858 |
+
if(is_wp_error($upgrader->skin->installer_error)){
|
1859 |
+
$message = $upgrader->skin->installer_error->get_error_message() .
|
1860 |
+
' (' . $upgrader->skin->installer_error->get_error_data() . ')';
|
1861 |
+
}
|
1862 |
+
}
|
1863 |
+
|
1864 |
+
if($plugin_is_active){
|
1865 |
+
//prevent redirects
|
1866 |
+
add_filter('wp_redirect', '__return_false');
|
1867 |
+
activate_plugin($plugin_id);
|
1868 |
+
}
|
1869 |
+
|
1870 |
+
}else{ //install
|
1871 |
+
|
1872 |
+
if($is_embedded){
|
1873 |
+
delete_plugins(array($plugin_id));
|
1874 |
+
}
|
1875 |
+
|
1876 |
+
$response['install'] = 1;
|
1877 |
+
$ret = $upgrader->install($data['url']);
|
1878 |
+
if(!$ret && !empty($upgrader->skin->installer_error)){
|
1879 |
+
if(is_wp_error($upgrader->skin->installer_error)){
|
1880 |
+
$message = $upgrader->skin->installer_error->get_error_message() .
|
1881 |
+
' (' . $upgrader->skin->installer_error->get_error_data() . ')';
|
1882 |
+
}
|
1883 |
+
}
|
1884 |
+
}
|
1885 |
+
|
1886 |
+
$plugins = get_plugins(); //read again
|
1887 |
+
|
1888 |
+
if($ret && !empty($_POST['activate'])){
|
1889 |
+
foreach($plugins as $id => $plugin){
|
1890 |
+
$wp_plugin_slug = dirname($id);
|
1891 |
+
if($wp_plugin_slug == $data['slug']){
|
1892 |
+
$plugin_version = $plugin['Version'];
|
1893 |
+
$plugin_id = $id;
|
1894 |
+
break;
|
1895 |
+
}
|
1896 |
+
}
|
1897 |
+
|
1898 |
+
}
|
1899 |
+
|
1900 |
+
}
|
1901 |
+
|
1902 |
+
} else { //subscription not valid
|
1903 |
+
|
1904 |
+
$ret = false;
|
1905 |
+
$message = __('Your subscription appears to no longer be valid. Please try to register again using a valid site key.', 'installer');
|
1906 |
+
}
|
1907 |
+
|
1908 |
+
$response['version'] = isset($plugin_version) ? $plugin_version : 0;
|
1909 |
+
$response['plugin_id'] = $plugin_id;
|
1910 |
+
$response['nonce'] = wp_create_nonce('activate_' . $plugin_id);
|
1911 |
+
$response['success'] = $ret;
|
1912 |
+
$response['message'] = $message;
|
1913 |
+
|
1914 |
+
echo json_encode( $response );
|
1915 |
+
exit;
|
1916 |
+
|
1917 |
+
}
|
1918 |
+
|
1919 |
+
public function download_plugin($slug, $url){
|
1920 |
+
|
1921 |
+
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
1922 |
+
require_once $this->plugin_path() . '/includes/installer-upgrader-skins.php';
|
1923 |
+
|
1924 |
+
$upgrader_skins = new Installer_Upgrader_Skins(); //use our custom (mute) Skin
|
1925 |
+
$upgrader = new Plugin_Upgrader($upgrader_skins);
|
1926 |
+
|
1927 |
+
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
|
1928 |
+
|
1929 |
+
$plugins = get_plugins();
|
1930 |
+
|
1931 |
+
$plugin_id = false;
|
1932 |
+
|
1933 |
+
//upgrade or install?
|
1934 |
+
foreach($plugins as $id => $plugin){
|
1935 |
+
$wp_plugin_slug = dirname($id);
|
1936 |
+
if($wp_plugin_slug == $slug){
|
1937 |
+
$plugin_id = $id;
|
1938 |
+
break;
|
1939 |
+
}
|
1940 |
+
}
|
1941 |
+
|
1942 |
+
if($plugin_id){ //upgrade
|
1943 |
+
|
1944 |
+
$plugin_is_active = is_plugin_active($plugin_id);
|
1945 |
+
|
1946 |
+
$ret = $upgrader->upgrade($plugin_id);
|
1947 |
+
|
1948 |
+
if($plugin_is_active){
|
1949 |
+
activate_plugin($plugin_id);
|
1950 |
+
}
|
1951 |
+
|
1952 |
+
}else{ //install
|
1953 |
+
$ret = $upgrader->install($url);
|
1954 |
+
}
|
1955 |
+
|
1956 |
+
return $ret;
|
1957 |
+
|
1958 |
+
}
|
1959 |
+
|
1960 |
+
public function activate_plugin(){
|
1961 |
+
|
1962 |
+
$error = '';
|
1963 |
+
|
1964 |
+
$plugin_id = sanitize_text_field ( $_POST['plugin_id'] );
|
1965 |
+
if(isset($_POST['nonce']) && $plugin_id && $_POST['nonce'] == wp_create_nonce('activate_' . $plugin_id )){
|
1966 |
+
|
1967 |
+
// Deactivate any embedded version
|
1968 |
+
$plugin_slug = dirname($plugin_id);
|
1969 |
+
$active_plugins = get_option('active_plugins');
|
1970 |
+
foreach($active_plugins as $plugin){
|
1971 |
+
$wp_plugin_slug = dirname($plugin);
|
1972 |
+
if($wp_plugin_slug == $plugin_slug . '-embedded'){
|
1973 |
+
deactivate_plugins(array($plugin));
|
1974 |
+
break;
|
1975 |
+
}
|
1976 |
+
}
|
1977 |
+
|
1978 |
+
//prevent redirects
|
1979 |
+
add_filter('wp_redirect', '__return_false', 10000);
|
1980 |
+
|
1981 |
+
$return = activate_plugin($plugin_id);
|
1982 |
+
|
1983 |
+
if(is_wp_error($return)){
|
1984 |
+
$error = $return->get_error_message();
|
1985 |
+
}
|
1986 |
+
|
1987 |
+
}else{
|
1988 |
+
$error = 'error';
|
1989 |
+
}
|
1990 |
+
|
1991 |
+
$ret = array('error' => $error);
|
1992 |
+
|
1993 |
+
echo json_encode($ret);
|
1994 |
+
exit;
|
1995 |
+
|
1996 |
+
}
|
1997 |
+
|
1998 |
+
public function custom_plugins_api_call($false, $action, $args){
|
1999 |
+
|
2000 |
+
if($action == 'plugin_information'){
|
2001 |
+
|
2002 |
+
$plugins = get_plugins();
|
2003 |
+
$plugin_names = array();
|
2004 |
+
foreach( $plugins as $plugin_id => $plugin ) {
|
2005 |
+
// plugins by WP slug which (plugin folder) which can be different
|
2006 |
+
// will use this to compare by title
|
2007 |
+
$plugin_names[ dirname( $plugin_id ) ] = array(
|
2008 |
+
'name' => $plugin['Name'],
|
2009 |
+
'title' => $plugin['Title'],
|
2010 |
+
);
|
2011 |
+
}
|
2012 |
+
|
2013 |
+
$slug = $args->slug;
|
2014 |
+
|
2015 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2016 |
+
|
2017 |
+
if(!$this->repository_has_valid_subscription($repository_id)){
|
2018 |
+
$site_key = false;
|
2019 |
+
}else{
|
2020 |
+
$site_key = $repository['subscription']['key'];
|
2021 |
+
}
|
2022 |
+
|
2023 |
+
foreach($repository['data']['packages'] as $package){
|
2024 |
+
|
2025 |
+
foreach($package['products'] as $product){
|
2026 |
+
|
2027 |
+
foreach($product['plugins'] as $plugin_slug){
|
2028 |
+
|
2029 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
2030 |
+
|
2031 |
+
if( $download['slug'] == $slug ||
|
2032 |
+
isset( $plugin_names[$slug] ) && (
|
2033 |
+
$plugin_names[$slug]['name'] == $download['name'] ||
|
2034 |
+
$plugin_names[$slug]['title'] == $download['name']
|
2035 |
+
)
|
2036 |
+
){
|
2037 |
+
|
2038 |
+
if( !empty( $download['free-on-wporg'] ) ){
|
2039 |
+
return false; // use data from wordpress.org
|
2040 |
+
}
|
2041 |
+
|
2042 |
+
$res = new stdClass();
|
2043 |
+
$res->external = true;
|
2044 |
+
|
2045 |
+
$res->name = $download['name'];
|
2046 |
+
$res->slug = $slug;
|
2047 |
+
$res->version = $download['version'];
|
2048 |
+
$res->author = '';
|
2049 |
+
$res->author_profile = '';
|
2050 |
+
$res->last_updated = $download['date'];
|
2051 |
+
|
2052 |
+
if($site_key){
|
2053 |
+
$res->download_link = $this->append_site_key_to_download_url($download['url'], $site_key, $repository_id);
|
2054 |
+
}
|
2055 |
+
|
2056 |
+
$res->homepage = $repository['data']['url'];
|
2057 |
+
$res->sections = array('Description' => $download['description'], 'Changelog' => $download['changelog']);
|
2058 |
+
|
2059 |
+
return $res;
|
2060 |
+
|
2061 |
+
}
|
2062 |
+
|
2063 |
+
}
|
2064 |
+
|
2065 |
+
}
|
2066 |
+
|
2067 |
+
}
|
2068 |
+
|
2069 |
+
}
|
2070 |
+
|
2071 |
+
}
|
2072 |
+
|
2073 |
+
return $false;
|
2074 |
+
|
2075 |
+
}
|
2076 |
+
|
2077 |
+
public function plugins_upgrade_check($update_plugins){
|
2078 |
+
|
2079 |
+
if(!empty($this->settings['repositories'])){
|
2080 |
+
|
2081 |
+
$plugins = get_plugins();
|
2082 |
+
|
2083 |
+
foreach($plugins as $plugin_id => $plugin){
|
2084 |
+
|
2085 |
+
$slug = dirname($plugin_id);
|
2086 |
+
if(empty($slug)) continue;
|
2087 |
+
|
2088 |
+
$version = $plugin['Version'];
|
2089 |
+
$name = $plugin['Name'];
|
2090 |
+
|
2091 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2092 |
+
|
2093 |
+
|
2094 |
+
if(!$this->repository_has_valid_subscription($repository_id)){
|
2095 |
+
$site_key = false;
|
2096 |
+
}else{
|
2097 |
+
$site_key = $repository['subscription']['key'];
|
2098 |
+
//$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
2099 |
+
}
|
2100 |
+
|
2101 |
+
foreach($repository['data']['packages'] as $package){
|
2102 |
+
|
2103 |
+
foreach($package['products'] as $product){
|
2104 |
+
|
2105 |
+
foreach($product['plugins'] as $plugin_slug){
|
2106 |
+
|
2107 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
2108 |
+
|
2109 |
+
if(!empty($download['free-on-wporg'])) {
|
2110 |
+
continue;
|
2111 |
+
}
|
2112 |
+
|
2113 |
+
if(empty($update_plugins->response[$plugin_id]) && ($download['slug'] == $slug || $download['name'] == $name ) && version_compare($download['version'], $version, '>')){
|
2114 |
+
|
2115 |
+
$response = new stdClass();
|
2116 |
+
$response->id = 0;
|
2117 |
+
$response->slug = $slug;
|
2118 |
+
$response->plugin = $plugin_id;
|
2119 |
+
$response->new_version = $download['version'];
|
2120 |
+
$response->upgrade_notice = '';
|
2121 |
+
$response->url = $download['url'];
|
2122 |
+
if($site_key){
|
2123 |
+
$response->package = $this->append_site_key_to_download_url($download['url'], $site_key, $repository_id);
|
2124 |
+
}
|
2125 |
+
$update_plugins->checked[$plugin_id] = $version;
|
2126 |
+
$update_plugins->response[$plugin_id] = $response;
|
2127 |
+
|
2128 |
+
}
|
2129 |
+
|
2130 |
+
}
|
2131 |
+
|
2132 |
+
}
|
2133 |
+
|
2134 |
+
}
|
2135 |
+
|
2136 |
+
}
|
2137 |
+
|
2138 |
+
}
|
2139 |
+
|
2140 |
+
}
|
2141 |
+
|
2142 |
+
return $update_plugins;
|
2143 |
+
|
2144 |
+
}
|
2145 |
+
|
2146 |
+
public function setup_plugins_page_notices(){
|
2147 |
+
|
2148 |
+
$plugins = get_plugins();
|
2149 |
+
|
2150 |
+
foreach($plugins as $plugin_id => $plugin){
|
2151 |
+
|
2152 |
+
$slug = dirname($plugin_id);
|
2153 |
+
if(empty($slug)) continue;
|
2154 |
+
|
2155 |
+
$name = $plugin['Name'];
|
2156 |
+
|
2157 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2158 |
+
|
2159 |
+
if(!$this->repository_has_valid_subscription($repository_id)){
|
2160 |
+
$site_key = false;
|
2161 |
+
}else{
|
2162 |
+
$site_key = $repository['subscription']['key'];
|
2163 |
+
}
|
2164 |
+
|
2165 |
+
foreach($repository['data']['packages'] as $package){
|
2166 |
+
|
2167 |
+
foreach($package['products'] as $product){
|
2168 |
+
|
2169 |
+
foreach($product['plugins'] as $plugin_slug){
|
2170 |
+
|
2171 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
2172 |
+
|
2173 |
+
if(!empty($download['free-on-wporg'])) {
|
2174 |
+
continue;
|
2175 |
+
}
|
2176 |
+
|
2177 |
+
if( $download['slug'] == $slug || $download['name'] == $name ){
|
2178 |
+
|
2179 |
+
if( !$site_key || !$this->plugin_is_registered($repository_id, $download['slug']) ){
|
2180 |
+
add_action( "after_plugin_row_" . $plugin_id, array($this, 'show_purchase_notice_under_plugin'), 10, 3 );
|
2181 |
+
}
|
2182 |
+
|
2183 |
+
}
|
2184 |
+
|
2185 |
+
}
|
2186 |
+
|
2187 |
+
}
|
2188 |
+
|
2189 |
+
}
|
2190 |
+
|
2191 |
+
}
|
2192 |
+
|
2193 |
+
}
|
2194 |
+
|
2195 |
+
}
|
2196 |
+
|
2197 |
+
public function show_purchase_notice_under_plugin($plugin_file, $plugin_data, $status){
|
2198 |
+
|
2199 |
+
$wp_list_table = _get_list_table('WP_Plugins_List_Table');
|
2200 |
+
$wp_version = preg_replace( '/-(.+)$/', '', $GLOBALS['wp_version'] );
|
2201 |
+
|
2202 |
+
if( version_compare( $wp_version, '4.6', '>=' ) ){
|
2203 |
+
|
2204 |
+
?>
|
2205 |
+
<tr class="plugin-update-tr installer-plugin-update-tr">
|
2206 |
+
<td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="plugin-update colspanchange">
|
2207 |
+
<div class="notice inline notice-warning notice-alt">
|
2208 |
+
<p class="installer-q-icon">
|
2209 |
+
<?php printf( __('You must have a valid subscription in order to get upgrades or support for this plugin. %sPurchase a subscription or enter an existing site key%s.', 'installer'),
|
2210 |
+
'<a href="' . $this->menu_url() . '">', '</a>'); ?>
|
2211 |
+
</p>
|
2212 |
+
</div>
|
2213 |
+
</td>
|
2214 |
+
</tr>
|
2215 |
+
<?php
|
2216 |
+
|
2217 |
+
} else {
|
2218 |
+
|
2219 |
+
?>
|
2220 |
+
<tr class="plugin-update-tr">
|
2221 |
+
<td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="plugin-update colspanchange">
|
2222 |
+
<div class="update-message installer-q-icon">
|
2223 |
+
<?php printf( __('You must have a valid subscription in order to get upgrades or support for this plugin. %sPurchase a subscription or enter an existing site key%s.', 'installer'),
|
2224 |
+
'<a href="' . $this->menu_url() . '">', '</a>'); ?>
|
2225 |
+
</div>
|
2226 |
+
</td>
|
2227 |
+
</tr>
|
2228 |
+
<?php
|
2229 |
+
|
2230 |
+
}
|
2231 |
+
|
2232 |
+
}
|
2233 |
+
|
2234 |
+
public function localize_strings(){
|
2235 |
+
|
2236 |
+
if(!empty($this->settings['repositories'])){
|
2237 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2238 |
+
//set name as call2action when don't have any
|
2239 |
+
//products
|
2240 |
+
foreach($repository['data']['packages'] as $package_id => $package){
|
2241 |
+
foreach($package['products'] as $product_id => $product){
|
2242 |
+
if(empty($product['call2action'])){
|
2243 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['call2action'] = $product['name'];
|
2244 |
+
}
|
2245 |
+
|
2246 |
+
foreach($product['upgrades'] as $idx => $upg){
|
2247 |
+
if(empty($upg['call2action'])){
|
2248 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$idx]['call2action'] = $upg['name'];
|
2249 |
+
}
|
2250 |
+
}
|
2251 |
+
|
2252 |
+
foreach($product['renewals'] as $idx => $rnw){
|
2253 |
+
if(empty($rnw['call2action'])){
|
2254 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['renewals'][$idx]['call2action'] = $rnw['name'];
|
2255 |
+
}
|
2256 |
+
|
2257 |
+
}
|
2258 |
+
|
2259 |
+
}
|
2260 |
+
}
|
2261 |
+
}
|
2262 |
+
}
|
2263 |
+
|
2264 |
+
global $sitepress;
|
2265 |
+
if(is_null($sitepress)){
|
2266 |
+
return;
|
2267 |
+
}
|
2268 |
+
|
2269 |
+
// default strings are always in English
|
2270 |
+
$user_admin_language = $sitepress->get_admin_language();
|
2271 |
+
|
2272 |
+
if($user_admin_language != 'en'){
|
2273 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2274 |
+
|
2275 |
+
$localization = $repository['data']['localization'];
|
2276 |
+
|
2277 |
+
//packages
|
2278 |
+
foreach($repository['data']['packages'] as $package_id => $package){
|
2279 |
+
|
2280 |
+
if( isset($localization['packages'][$package_id]['name'][$user_admin_language]) ){
|
2281 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['name'] = $localization['packages'][$package_id]['name'][$user_admin_language];
|
2282 |
+
}
|
2283 |
+
if( isset($localization['packages'][$package_id]['description'][$user_admin_language]) ){
|
2284 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['description'] = $localization['packages'][$package_id]['description'][$user_admin_language];
|
2285 |
+
}
|
2286 |
+
|
2287 |
+
}
|
2288 |
+
|
2289 |
+
//products
|
2290 |
+
foreach($repository['data']['packages'] as $package_id => $package){
|
2291 |
+
foreach($package['products'] as $product_id => $product){
|
2292 |
+
|
2293 |
+
if( isset($localization['products'][$product_id]['name'][$user_admin_language]) ){
|
2294 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['name']
|
2295 |
+
= $localization['products'][$product_id]['name'][$user_admin_language];
|
2296 |
+
}
|
2297 |
+
if( isset($localization['products'][$product_id]['description'][$user_admin_language]) ){
|
2298 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['description']
|
2299 |
+
= $localization['products'][$product_id]['description'][$user_admin_language];
|
2300 |
+
}
|
2301 |
+
if( isset($localization['products'][$product_id]['call2action'][$user_admin_language]) ){
|
2302 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['name']
|
2303 |
+
= $localization['products'][$product_id]['call2action'][$user_admin_language];
|
2304 |
+
}
|
2305 |
+
|
2306 |
+
|
2307 |
+
}
|
2308 |
+
}
|
2309 |
+
|
2310 |
+
//subscription info
|
2311 |
+
if(isset($repository['data']['subscriptions_meta']['expiration'])){
|
2312 |
+
foreach($repository['data']['subscriptions_meta']['expiration'] as $subscription_id => $note){
|
2313 |
+
if(isset($localization['subscriptions-notes'][$subscription_id]['expiration-warning'][$user_admin_language])){
|
2314 |
+
$this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_id]['warning_message']
|
2315 |
+
= $localization['subscriptions-notes'][$subscription_id]['expiration-warning'][$user_admin_language];
|
2316 |
+
}
|
2317 |
+
}
|
2318 |
+
}
|
2319 |
+
|
2320 |
+
}
|
2321 |
+
}
|
2322 |
+
|
2323 |
+
}
|
2324 |
+
|
2325 |
+
public function get_matching_cp($repository, $args = array()){
|
2326 |
+
$match = false;
|
2327 |
+
|
2328 |
+
|
2329 |
+
$cp_name = $cp_author = false;
|
2330 |
+
|
2331 |
+
if(isset($this->config['src_name']) && isset($this->config['src_author'])){
|
2332 |
+
|
2333 |
+
$cp_name = $this->config['src_name'];
|
2334 |
+
$cp_author = $this->config['src_author'];
|
2335 |
+
|
2336 |
+
}elseif(isset($args['src_name']) && isset($args['src_author'])){
|
2337 |
+
|
2338 |
+
$cp_name = $args['src_name'];
|
2339 |
+
$cp_author = $args['src_author'];
|
2340 |
+
|
2341 |
+
}
|
2342 |
+
|
2343 |
+
if(isset($repository['data']['marketing_cp'])){
|
2344 |
+
|
2345 |
+
foreach($repository['data']['marketing_cp'] as $cp){
|
2346 |
+
|
2347 |
+
if(!empty($cp['exp']) && time() > $cp['exp']){
|
2348 |
+
continue;
|
2349 |
+
}
|
2350 |
+
|
2351 |
+
//Use theme_name for plugins too
|
2352 |
+
if(!empty($cp['theme_name'])){
|
2353 |
+
if($cp['author_name'] == $cp_author && $cp['theme_name'] == $cp_name){
|
2354 |
+
$match = $cp;
|
2355 |
+
continue;
|
2356 |
+
}
|
2357 |
+
}else{
|
2358 |
+
if($cp['author_name'] == $cp_author){
|
2359 |
+
$match = $cp;
|
2360 |
+
continue;
|
2361 |
+
}
|
2362 |
+
}
|
2363 |
+
|
2364 |
+
}
|
2365 |
+
|
2366 |
+
}
|
2367 |
+
|
2368 |
+
return $match;
|
2369 |
+
}
|
2370 |
+
|
2371 |
+
public function set_filtered_prices($args = array()){
|
2372 |
+
|
2373 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2374 |
+
|
2375 |
+
$match = $this->get_matching_cp($repository, $args);
|
2376 |
+
|
2377 |
+
if(empty($match)) continue;
|
2378 |
+
|
2379 |
+
foreach($repository['data']['packages'] as $package_id => $package){
|
2380 |
+
|
2381 |
+
foreach($package['products'] as $product_id => $product){
|
2382 |
+
|
2383 |
+
if($match['dtp'] == '%'){
|
2384 |
+
$fprice = round( $product['price'] * (1 - $match['amt']/100), 2 );
|
2385 |
+
$fprice = $fprice != round($fprice) ? sprintf('%.2f', $fprice) : round($fprice, 0);
|
2386 |
+
}elseif($match['dtp'] == '-'){
|
2387 |
+
$fprice = $product['price'] - $match['amt'];
|
2388 |
+
}else{
|
2389 |
+
$fprice = $product['price'];
|
2390 |
+
}
|
2391 |
+
|
2392 |
+
if($fprice){
|
2393 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['price_disc'] = $fprice;
|
2394 |
+
|
2395 |
+
$url_glue = false !== strpos($this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['url'], '?') ? '&' : '?';
|
2396 |
+
$cpndata = base64_encode(json_encode(array('theme_author' => $match['author_name'], 'theme_name' => $match['theme_name'], 'vlc' => $match['vlc'])));
|
2397 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['url'] .= $url_glue . 'cpn=' . $cpndata;
|
2398 |
+
|
2399 |
+
foreach($product['upgrades'] as $upgrade_id => $upgrade){
|
2400 |
+
|
2401 |
+
$fprice = false;
|
2402 |
+
if($match['dtp'] == '%'){
|
2403 |
+
$fprice = round( $upgrade['price'] * (1 - $match['amt']/100), 2 );
|
2404 |
+
$fprice = $fprice != round($fprice) ? sprintf('%.2f', $fprice) : round($fprice, 0);
|
2405 |
+
}elseif($match['dtp'] == '-'){
|
2406 |
+
$fprice = $upgrade['price'] - $match['amt'];
|
2407 |
+
}
|
2408 |
+
if($fprice){
|
2409 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$upgrade_id]['price_disc'] = $fprice;
|
2410 |
+
$this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$upgrade_id]['url'] .= $url_glue . 'cpn=' . $cpndata;
|
2411 |
+
}
|
2412 |
+
|
2413 |
+
|
2414 |
+
}
|
2415 |
+
|
2416 |
+
}
|
2417 |
+
|
2418 |
+
}
|
2419 |
+
|
2420 |
+
}
|
2421 |
+
|
2422 |
+
}
|
2423 |
+
|
2424 |
+
}
|
2425 |
+
|
2426 |
+
public function set_hierarchy_and_order(){
|
2427 |
+
|
2428 |
+
//2 levels
|
2429 |
+
if(!empty($this->settings['repositories'])) {
|
2430 |
+
foreach ($this->settings['repositories'] as $repository_id => $repository) {
|
2431 |
+
|
2432 |
+
if( empty( $repository['data']['packages'] ) ) continue;
|
2433 |
+
|
2434 |
+
$all_packages = $repository['data']['packages'];
|
2435 |
+
$ordered_packages = array();
|
2436 |
+
|
2437 |
+
//backward compatibility - 'order'
|
2438 |
+
foreach($all_packages as $k => $v){
|
2439 |
+
if(!isset($v['order'])){
|
2440 |
+
$all_packages[$k]['order'] = 0;
|
2441 |
+
}
|
2442 |
+
}
|
2443 |
+
|
2444 |
+
//select parents
|
2445 |
+
foreach ($all_packages as $package_id => $package) {
|
2446 |
+
if(empty($package['parent'])){
|
2447 |
+
$ordered_packages[$package_id] = $package;
|
2448 |
+
}
|
2449 |
+
}
|
2450 |
+
|
2451 |
+
//add sub-packages
|
2452 |
+
foreach($all_packages as $package_id => $package){
|
2453 |
+
if(!empty($package['parent'])) {
|
2454 |
+
if(isset($ordered_packages[$package['parent']])){
|
2455 |
+
$ordered_packages[$package['parent']]['sub-packages'][$package_id] = $package;
|
2456 |
+
}
|
2457 |
+
}
|
2458 |
+
}
|
2459 |
+
|
2460 |
+
// order parents
|
2461 |
+
usort($ordered_packages, array($this, '_order_packages_callback'));
|
2462 |
+
//order sub-packages
|
2463 |
+
foreach($ordered_packages as $package_id => $package){
|
2464 |
+
if(!empty($package['sub-packages'])) {
|
2465 |
+
usort($ordered_packages[$package_id]['sub-packages'], create_function('$a, $b', 'return $a[\'order\'] > $b[\'order\'];'));
|
2466 |
+
}
|
2467 |
+
}
|
2468 |
+
|
2469 |
+
$this->settings['repositories'][$repository_id]['data']['packages'] = $ordered_packages;
|
2470 |
+
|
2471 |
+
|
2472 |
+
}
|
2473 |
+
}
|
2474 |
+
|
2475 |
+
|
2476 |
+
}
|
2477 |
+
|
2478 |
+
public function _order_packages_callback($a, $b){
|
2479 |
+
return $a['order'] > $b['order'];
|
2480 |
+
}
|
2481 |
+
|
2482 |
+
public function get_support_tag_by_name( $name, $repository ){
|
2483 |
+
|
2484 |
+
if( is_array($this->settings['repositories'][$repository]['data']['support_tags'] )){
|
2485 |
+
foreach( $this->settings['repositories'][$repository]['data']['support_tags'] as $support_tag){
|
2486 |
+
if( $support_tag['name'] == $name ){
|
2487 |
+
return $support_tag['url'];
|
2488 |
+
}
|
2489 |
+
}
|
2490 |
+
}
|
2491 |
+
|
2492 |
+
return false;
|
2493 |
+
}
|
2494 |
+
|
2495 |
+
public function plugin_upgrade_custom_errors(){
|
2496 |
+
|
2497 |
+
if ( isset($_REQUEST['action']) ) {
|
2498 |
+
|
2499 |
+
$action = isset($_REQUEST['action']) ? sanitize_text_field ( $_REQUEST['action'] ) : '';
|
2500 |
+
|
2501 |
+
//bulk mode
|
2502 |
+
if('update-selected' == $action) {
|
2503 |
+
|
2504 |
+
global $plugins;
|
2505 |
+
|
2506 |
+
if(isset($plugins) && is_array($plugins)) {
|
2507 |
+
|
2508 |
+
foreach ($plugins as $k => $plugin) {
|
2509 |
+
$plugin_repository = false;
|
2510 |
+
|
2511 |
+
$wp_plugin_slug = dirname($plugin);
|
2512 |
+
|
2513 |
+
foreach ($this->settings['repositories'] as $repository_id => $repository) {
|
2514 |
+
|
2515 |
+
foreach ($repository['data']['packages'] as $package) {
|
2516 |
+
|
2517 |
+
foreach ($package['products'] as $product) {
|
2518 |
+
|
2519 |
+
foreach ($product['plugins'] as $plugin_slug) {
|
2520 |
+
|
2521 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
2522 |
+
|
2523 |
+
if ($download['slug'] == $wp_plugin_slug) {
|
2524 |
+
$plugin_repository = $repository_id;
|
2525 |
+
$product_name = $repository['data']['product-name'];
|
2526 |
+
$plugin_name = $download['name'];
|
2527 |
+
$free_on_wporg = !empty($download['free-on-wporg']);
|
2528 |
+
break;
|
2529 |
+
}
|
2530 |
+
|
2531 |
+
}
|
2532 |
+
|
2533 |
+
}
|
2534 |
+
|
2535 |
+
}
|
2536 |
+
|
2537 |
+
}
|
2538 |
+
|
2539 |
+
if ($plugin_repository) {
|
2540 |
+
|
2541 |
+
//validate subscription
|
2542 |
+
static $sub_cache = array();
|
2543 |
+
|
2544 |
+
if(empty($sub_cache[$plugin_repository])){
|
2545 |
+
$site_key = $this->get_repository_site_key($plugin_repository);
|
2546 |
+
if ($site_key) {
|
2547 |
+
$subscription_data = $this->fetch_subscription_data( $plugin_repository, $site_key, self::SITE_KEY_VALIDATION_SOURCE_REVALIDATION );
|
2548 |
+
}
|
2549 |
+
|
2550 |
+
$sub_cache[$plugin_repository]['site_key'] = $site_key;
|
2551 |
+
$sub_cache[$plugin_repository]['subscription_data'] = isset($subscription_data) ? $subscription_data : false;
|
2552 |
+
}else{
|
2553 |
+
|
2554 |
+
$site_key = $sub_cache[$plugin_repository]['site_key'];
|
2555 |
+
$subscription_data = $sub_cache[$plugin_repository]['subscription_data'];
|
2556 |
+
|
2557 |
+
}
|
2558 |
+
|
2559 |
+
if(!$site_key && !empty($free_on_wporg)){ // allow the download from wp.org
|
2560 |
+
continue;
|
2561 |
+
}
|
2562 |
+
|
2563 |
+
if (empty($site_key) || empty($subscription_data)) {
|
2564 |
+
|
2565 |
+
|
2566 |
+
$error_message = sprintf(__("%s cannot update because your site's registration is not valid. Please %sregister %s%s again for this site first.", 'installer'),
|
2567 |
+
'<strong>' . $plugin_name . '</strong>', '<a target="_top" href="' . $this->menu_url() . '&validate_repository=' . $plugin_repository .
|
2568 |
+
'#repository-' . $plugin_repository . '">', $product_name, '</a>');
|
2569 |
+
|
2570 |
+
echo '<div class="updated error"><p>' . $error_message . '</p></div>';
|
2571 |
+
|
2572 |
+
unset($plugins[$k]);
|
2573 |
+
|
2574 |
+
|
2575 |
+
}
|
2576 |
+
|
2577 |
+
}
|
2578 |
+
|
2579 |
+
}
|
2580 |
+
|
2581 |
+
}
|
2582 |
+
|
2583 |
+
}
|
2584 |
+
|
2585 |
+
|
2586 |
+
if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
|
2587 |
+
|
2588 |
+
$plugin = isset($_REQUEST['plugin']) ? trim( sanitize_text_field ( $_REQUEST['plugin'] ) ) : '';
|
2589 |
+
|
2590 |
+
$wp_plugin_slug = dirname($plugin);
|
2591 |
+
|
2592 |
+
$plugin_repository = false;
|
2593 |
+
|
2594 |
+
foreach($this->settings['repositories'] as $repository_id => $repository){
|
2595 |
+
|
2596 |
+
foreach($repository['data']['packages'] as $package){
|
2597 |
+
|
2598 |
+
foreach($package['products'] as $product){
|
2599 |
+
|
2600 |
+
foreach($product['plugins'] as $plugin_slug){
|
2601 |
+
$download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
|
2602 |
+
|
2603 |
+
//match by folder, will change to match by name and folder
|
2604 |
+
if($download['slug'] == $wp_plugin_slug) {
|
2605 |
+
$plugin_repository = $repository_id;
|
2606 |
+
$product_name = $repository['data']['product-name'];
|
2607 |
+
$plugin_name = $download['name'];
|
2608 |
+
$free_on_wporg = !empty($download['free-on-wporg']);
|
2609 |
+
break;
|
2610 |
+
}
|
2611 |
+
|
2612 |
+
}
|
2613 |
+
|
2614 |
+
}
|
2615 |
+
|
2616 |
+
}
|
2617 |
+
|
2618 |
+
}
|
2619 |
+
|
2620 |
+
if($plugin_repository) {
|
2621 |
+
|
2622 |
+
//validate subscription
|
2623 |
+
$site_key = $this->get_repository_site_key($plugin_repository);
|
2624 |
+
if ($site_key) {
|
2625 |
+
$subscription_data = $this->fetch_subscription_data( $plugin_repository, $site_key, self::SITE_KEY_VALIDATION_SOURCE_REVALIDATION );
|
2626 |
+
}
|
2627 |
+
|
2628 |
+
if ( (empty($site_key) || empty($subscription_data)) && empty($free_on_wporg)) {
|
2629 |
+
|
2630 |
+
$error_message = sprintf(__("%s cannot update because your site's registration is not valid. Please %sregister %s%s again for this site first.", 'installer'),
|
2631 |
+
'<strong>'.$plugin_name . '</strong>', '<a href="' . $this->menu_url() . '&validate_repository=' . $plugin_repository .
|
2632 |
+
'#repository-' . $plugin_repository . '">', $product_name, '</a>');
|
2633 |
+
|
2634 |
+
if(defined('DOING_AJAX')){ //WP 4.2
|
2635 |
+
|
2636 |
+
$status = array(
|
2637 |
+
'update' => 'plugin',
|
2638 |
+
'plugin' => $plugin,
|
2639 |
+
'slug' => sanitize_key( $_POST['slug'] ),
|
2640 |
+
'oldVersion' => '',
|
2641 |
+
'newVersion' => '',
|
2642 |
+
);
|
2643 |
+
|
2644 |
+
$status['errorCode'] = 'wp_installer_invalid_subscription';
|
2645 |
+
$status['error'] = $error_message;
|
2646 |
+
|
2647 |
+
wp_send_json_error( $status );
|
2648 |
+
|
2649 |
+
} else { // WP 4.1.1
|
2650 |
+
echo '<div class="updated error"><p>' . $error_message . '</p></div>';
|
2651 |
+
|
2652 |
+
|
2653 |
+
echo '<div class="wrap">';
|
2654 |
+
echo '<h2>' . __('Update Plugin') . '</h2>';
|
2655 |
+
echo '<a href="' . admin_url('plugins.php') . '">' . __('Return to the plugins page') . '</a>';
|
2656 |
+
echo '</div>';
|
2657 |
+
require_once(ABSPATH . 'wp-admin/admin-footer.php');
|
2658 |
+
exit;
|
2659 |
+
|
2660 |
+
}
|
2661 |
+
|
2662 |
+
}
|
2663 |
+
|
2664 |
+
|
2665 |
+
}
|
2666 |
+
|
2667 |
+
}
|
2668 |
+
}
|
2669 |
+
|
2670 |
+
}
|
2671 |
+
|
2672 |
+
}
|
library/otgs/installer/includes/translation-service-info.class.php
CHANGED
@@ -1,40 +1,40 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class TranslationServiceInfo{
|
4 |
-
|
5 |
-
function __construct(){
|
6 |
-
|
7 |
-
add_action('installer_fetched_subscription_data',array($this, 'save_info'), 10, 2);
|
8 |
-
|
9 |
-
}
|
10 |
-
|
11 |
-
function save_info($data, $repository_id) {
|
12 |
-
|
13 |
-
$ts_info = isset( WP_Installer()->settings['repositories'][$repository_id]['ts_info'] ) ?
|
14 |
-
WP_Installer()->settings['repositories'][$repository_id]['ts_info'] : false;
|
15 |
-
|
16 |
-
$save_settings = false;
|
17 |
-
if(isset($data->ts_info['preferred']) && empty($ts_info['preferred'])){
|
18 |
-
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'] = $data->ts_info['preferred'];
|
19 |
-
$save_settings = true;
|
20 |
-
}
|
21 |
-
|
22 |
-
if(isset($data->ts_info['referal']) && empty($ts_info['referal'])){
|
23 |
-
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['referal'] = $data->ts_info['referal'];
|
24 |
-
$save_settings = true;
|
25 |
-
}
|
26 |
-
|
27 |
-
if ( !empty( $data->ts_info['client_id'] ) ) { // can be updated
|
28 |
-
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['client_id'] = $data->ts_info['client_id'];
|
29 |
-
$save_settings = true;
|
30 |
-
}
|
31 |
-
|
32 |
-
if($save_settings){
|
33 |
-
WP_Installer()->save_settings();
|
34 |
-
}
|
35 |
-
|
36 |
-
}
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
new TranslationServiceInfo();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class TranslationServiceInfo{
|
4 |
+
|
5 |
+
function __construct(){
|
6 |
+
|
7 |
+
add_action('installer_fetched_subscription_data',array($this, 'save_info'), 10, 2);
|
8 |
+
|
9 |
+
}
|
10 |
+
|
11 |
+
function save_info($data, $repository_id) {
|
12 |
+
|
13 |
+
$ts_info = isset( WP_Installer()->settings['repositories'][$repository_id]['ts_info'] ) ?
|
14 |
+
WP_Installer()->settings['repositories'][$repository_id]['ts_info'] : false;
|
15 |
+
|
16 |
+
$save_settings = false;
|
17 |
+
if(isset($data->ts_info['preferred']) && empty($ts_info['preferred'])){
|
18 |
+
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['preferred'] = $data->ts_info['preferred'];
|
19 |
+
$save_settings = true;
|
20 |
+
}
|
21 |
+
|
22 |
+
if(isset($data->ts_info['referal']) && empty($ts_info['referal'])){
|
23 |
+
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['referal'] = $data->ts_info['referal'];
|
24 |
+
$save_settings = true;
|
25 |
+
}
|
26 |
+
|
27 |
+
if ( !empty( $data->ts_info['client_id'] ) ) { // can be updated
|
28 |
+
WP_Installer()->settings['repositories'][$repository_id]['ts_info']['client_id'] = $data->ts_info['client_id'];
|
29 |
+
$save_settings = true;
|
30 |
+
}
|
31 |
+
|
32 |
+
if($save_settings){
|
33 |
+
WP_Installer()->save_settings();
|
34 |
+
}
|
35 |
+
|
36 |
+
}
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
new TranslationServiceInfo();
|
library/otgs/installer/installer.php
CHANGED
@@ -1,22 +1,22 @@
|
|
1 |
-
<?php
|
2 |
-
define('WP_INSTALLER_VERSION', '1.7.
|
3 |
-
|
4 |
-
include_once dirname(__FILE__) . '/includes/installer.class.php';
|
5 |
-
|
6 |
-
function WP_Installer() {
|
7 |
-
return WP_Installer::instance();
|
8 |
-
}
|
9 |
-
|
10 |
-
|
11 |
-
WP_Installer();
|
12 |
-
|
13 |
-
include_once WP_Installer()->plugin_path() . '/includes/installer-api.php';
|
14 |
-
include_once WP_Installer()->plugin_path() . '/includes/translation-service-info.class.php';
|
15 |
-
include_once WP_Installer()->plugin_path() . '/includes/class-installer-dependencies.php';
|
16 |
-
|
17 |
-
// Ext function
|
18 |
-
function WP_Installer_Show_Products($args = array()){
|
19 |
-
|
20 |
-
WP_Installer()->show_products($args);
|
21 |
-
|
22 |
}
|
1 |
+
<?php
|
2 |
+
define('WP_INSTALLER_VERSION', '1.7.13');
|
3 |
+
|
4 |
+
include_once dirname(__FILE__) . '/includes/installer.class.php';
|
5 |
+
|
6 |
+
function WP_Installer() {
|
7 |
+
return WP_Installer::instance();
|
8 |
+
}
|
9 |
+
|
10 |
+
|
11 |
+
WP_Installer();
|
12 |
+
|
13 |
+
include_once WP_Installer()->plugin_path() . '/includes/installer-api.php';
|
14 |
+
include_once WP_Installer()->plugin_path() . '/includes/translation-service-info.class.php';
|
15 |
+
include_once WP_Installer()->plugin_path() . '/includes/class-installer-dependencies.php';
|
16 |
+
|
17 |
+
// Ext function
|
18 |
+
function WP_Installer_Show_Products($args = array()){
|
19 |
+
|
20 |
+
WP_Installer()->show_products($args);
|
21 |
+
|
22 |
}
|
library/otgs/installer/loader.php
CHANGED
@@ -1,151 +1,151 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly
|
5 |
-
}
|
6 |
-
|
7 |
-
//It should only be loaded on the admin side
|
8 |
-
if( !is_admin() ){
|
9 |
-
if(!function_exists('WP_Installer_Setup')){ function WP_Installer_Setup(){} }
|
10 |
-
$wp_installer_instance = null;
|
11 |
-
return;
|
12 |
-
}
|
13 |
-
|
14 |
-
|
15 |
-
$wp_installer_instance = dirname(__FILE__) . '/installer.php';
|
16 |
-
|
17 |
-
|
18 |
-
// Global stack of instances
|
19 |
-
global $wp_installer_instances;
|
20 |
-
$wp_installer_instances[$wp_installer_instance] = array(
|
21 |
-
'bootfile' => $wp_installer_instance,
|
22 |
-
'version' => '1.7.
|
23 |
-
);
|
24 |
-
|
25 |
-
|
26 |
-
/* EXCEPTIONS ********************************************************************************************/
|
27 |
-
// Exception: When WPML prior 3.2 is used, that instance must be used regardless of another newer instance
|
28 |
-
// Case 1: WPML loaded before Types - eliminate other instances
|
29 |
-
if( defined('ICL_SITEPRESS_VERSION') && version_compare(ICL_SITEPRESS_VERSION, '3.2', '<') ) {
|
30 |
-
foreach($wp_installer_instances as $key => $instance) {
|
31 |
-
if(isset($instance['args']['site_key_nags'])){
|
32 |
-
$wp_installer_instances[$key]['version'] = '9.9';
|
33 |
-
}else{
|
34 |
-
$wp_installer_instances[$key]['version'] = '0';
|
35 |
-
}
|
36 |
-
}
|
37 |
-
}
|
38 |
-
|
39 |
-
// Exception: Types 1.8.9 (Installer 1.7.0) with WPML before 3.3 (Installer before 1.7.0)
|
40 |
-
// New products file http://d2salfytceyqoe.cloudfront.net/wpml-products33.json overrides the old one
|
41 |
-
// while the WPML's instance is being used
|
42 |
-
// => Force using the new Installer Instance
|
43 |
-
if( defined('ICL_SITEPRESS_VERSION') && version_compare(ICL_SITEPRESS_VERSION, '3.3.1', '<') ) {
|
44 |
-
|
45 |
-
// if Installer 1.7.0+ is present, unregister Installer from old WPML
|
46 |
-
// Force Installer 1.7.0+ being used over older Installer versions
|
47 |
-
$installer_171_plus_on = false;
|
48 |
-
foreach($wp_installer_instances as $key => $instance) {
|
49 |
-
if( version_compare( $instance['version'], '1.7.1', '>=' ) ){
|
50 |
-
$installer_171_plus_on = true;
|
51 |
-
break;
|
52 |
-
}
|
53 |
-
}
|
54 |
-
|
55 |
-
if( $installer_171_plus_on ){
|
56 |
-
foreach($wp_installer_instances as $key => $instance) {
|
57 |
-
|
58 |
-
if( version_compare( $instance['version'], '1.7.0', '<' ) ){
|
59 |
-
unset( $wp_installer_instances[$key] );
|
60 |
-
}
|
61 |
-
|
62 |
-
}
|
63 |
-
}
|
64 |
-
|
65 |
-
}
|
66 |
-
|
67 |
-
// Exception: When using the embedded plugins module allow the set up to run completely with the
|
68 |
-
// Installer instance that triggers it
|
69 |
-
if( isset( $_POST['installer_instance'] ) && isset( $wp_installer_instances[$_POST['installer_instance']] ) ){
|
70 |
-
$wp_installer_instances[$_POST['installer_instance']]['version'] = '999';
|
71 |
-
}
|
72 |
-
/* EXCEPTIONS ********************************************************************************************/
|
73 |
-
|
74 |
-
|
75 |
-
// Only one of these in the end
|
76 |
-
remove_action('after_setup_theme', 'wpml_installer_instance_delegator', 1);
|
77 |
-
add_action('after_setup_theme', 'wpml_installer_instance_delegator', 1);
|
78 |
-
|
79 |
-
// When all plugins load pick the newest version
|
80 |
-
if(!function_exists('wpml_installer_instance_delegator')){
|
81 |
-
function wpml_installer_instance_delegator(){
|
82 |
-
global $wp_installer_instances;
|
83 |
-
|
84 |
-
// version based election
|
85 |
-
foreach($wp_installer_instances as $instance){
|
86 |
-
|
87 |
-
if(!isset($delegate)){
|
88 |
-
$delegate = $instance;
|
89 |
-
continue;
|
90 |
-
}
|
91 |
-
|
92 |
-
if(version_compare($instance['version'], $delegate['version'], '>')){
|
93 |
-
$delegate = $instance;
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
// priority based election
|
98 |
-
$highest_priority = null;
|
99 |
-
foreach($wp_installer_instances as $instance) {
|
100 |
-
if(isset($instance['args']['high_priority'])){
|
101 |
-
if(is_null($highest_priority) || $instance['args']['high_priority'] <= $highest_priority){
|
102 |
-
$highest_priority = $instance['args']['high_priority'];
|
103 |
-
$delegate = $instance;
|
104 |
-
}
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
// Exception: When WPML prior 3.2 is used, that instance must be used regardless of another newer instance
|
109 |
-
// Case 2: WPML loaded after Types
|
110 |
-
if( defined('ICL_SITEPRESS_VERSION') && version_compare(ICL_SITEPRESS_VERSION, '3.2', '<') ) {
|
111 |
-
foreach($wp_installer_instances as $key => $instance) {
|
112 |
-
if(isset($instance['args']['site_key_nags'])){
|
113 |
-
$delegate = $instance;
|
114 |
-
$wp_installer_instances = array($key => $delegate); //Eliminate other instances
|
115 |
-
break;
|
116 |
-
}
|
117 |
-
}
|
118 |
-
}
|
119 |
-
|
120 |
-
include_once $delegate['bootfile'];
|
121 |
-
|
122 |
-
// set configuration
|
123 |
-
if(strpos(realpath($delegate['bootfile']), realpath(TEMPLATEPATH)) === 0){
|
124 |
-
$delegate['args']['in_theme_folder'] = dirname(ltrim(str_replace(realpath(TEMPLATEPATH), '', realpath($delegate['bootfile'])), '\\/'));
|
125 |
-
}
|
126 |
-
if(isset($delegate['args']) && is_array($delegate['args'])){
|
127 |
-
foreach($delegate['args'] as $key => $value){
|
128 |
-
WP_Installer()->set_config($key, $value);
|
129 |
-
}
|
130 |
-
}
|
131 |
-
|
132 |
-
}
|
133 |
-
}
|
134 |
-
|
135 |
-
if(!function_exists('WP_Installer_Setup')){
|
136 |
-
|
137 |
-
// $args:
|
138 |
-
// plugins_install_tab = true|false (default: true)
|
139 |
-
// repositories_include = array() (default: all)
|
140 |
-
// repositories_exclude = array() (default: none)
|
141 |
-
// template = name (default: default)
|
142 |
-
//
|
143 |
-
// Ext function
|
144 |
-
function WP_Installer_Setup($wp_installer_instance, $args = array()){
|
145 |
-
global $wp_installer_instances;
|
146 |
-
|
147 |
-
$wp_installer_instances[$wp_installer_instance]['args'] = $args;
|
148 |
-
|
149 |
-
}
|
150 |
-
|
151 |
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit; // Exit if accessed directly
|
5 |
+
}
|
6 |
+
|
7 |
+
//It should only be loaded on the admin side
|
8 |
+
if( !is_admin() ){
|
9 |
+
if(!function_exists('WP_Installer_Setup')){ function WP_Installer_Setup(){} }
|
10 |
+
$wp_installer_instance = null;
|
11 |
+
return;
|
12 |
+
}
|
13 |
+
|
14 |
+
|
15 |
+
$wp_installer_instance = dirname(__FILE__) . '/installer.php';
|
16 |
+
|
17 |
+
|
18 |
+
// Global stack of instances
|
19 |
+
global $wp_installer_instances;
|
20 |
+
$wp_installer_instances[$wp_installer_instance] = array(
|
21 |
+
'bootfile' => $wp_installer_instance,
|
22 |
+
'version' => '1.7.13'
|
23 |
+
);
|
24 |
+
|
25 |
+
|
26 |
+
/* EXCEPTIONS ********************************************************************************************/
|
27 |
+
// Exception: When WPML prior 3.2 is used, that instance must be used regardless of another newer instance
|
28 |
+
// Case 1: WPML loaded before Types - eliminate other instances
|
29 |
+
if( defined('ICL_SITEPRESS_VERSION') && version_compare(ICL_SITEPRESS_VERSION, '3.2', '<') ) {
|
30 |
+
foreach($wp_installer_instances as $key => $instance) {
|
31 |
+
if(isset($instance['args']['site_key_nags'])){
|
32 |
+
$wp_installer_instances[$key]['version'] = '9.9';
|
33 |
+
}else{
|
34 |
+
$wp_installer_instances[$key]['version'] = '0';
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
// Exception: Types 1.8.9 (Installer 1.7.0) with WPML before 3.3 (Installer before 1.7.0)
|
40 |
+
// New products file http://d2salfytceyqoe.cloudfront.net/wpml-products33.json overrides the old one
|
41 |
+
// while the WPML's instance is being used
|
42 |
+
// => Force using the new Installer Instance
|
43 |
+
if( defined('ICL_SITEPRESS_VERSION') && version_compare(ICL_SITEPRESS_VERSION, '3.3.1', '<') ) {
|
44 |
+
|
45 |
+
// if Installer 1.7.0+ is present, unregister Installer from old WPML
|
46 |
+
// Force Installer 1.7.0+ being used over older Installer versions
|
47 |
+
$installer_171_plus_on = false;
|
48 |
+
foreach($wp_installer_instances as $key => $instance) {
|
49 |
+
if( version_compare( $instance['version'], '1.7.1', '>=' ) ){
|
50 |
+
$installer_171_plus_on = true;
|
51 |
+
break;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
if( $installer_171_plus_on ){
|
56 |
+
foreach($wp_installer_instances as $key => $instance) {
|
57 |
+
|
58 |
+
if( version_compare( $instance['version'], '1.7.0', '<' ) ){
|
59 |
+
unset( $wp_installer_instances[$key] );
|
60 |
+
}
|
61 |
+
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
// Exception: When using the embedded plugins module allow the set up to run completely with the
|
68 |
+
// Installer instance that triggers it
|
69 |
+
if( isset( $_POST['installer_instance'] ) && isset( $wp_installer_instances[$_POST['installer_instance']] ) ){
|
70 |
+
$wp_installer_instances[$_POST['installer_instance']]['version'] = '999';
|
71 |
+
}
|
72 |
+
/* EXCEPTIONS ********************************************************************************************/
|
73 |
+
|
74 |
+
|
75 |
+
// Only one of these in the end
|
76 |
+
remove_action('after_setup_theme', 'wpml_installer_instance_delegator', 1);
|
77 |
+
add_action('after_setup_theme', 'wpml_installer_instance_delegator', 1);
|
78 |
+
|
79 |
+
// When all plugins load pick the newest version
|
80 |
+
if(!function_exists('wpml_installer_instance_delegator')){
|
81 |
+
function wpml_installer_instance_delegator(){
|
82 |
+
global $wp_installer_instances;
|
83 |
+
|
84 |
+
// version based election
|
85 |
+
foreach($wp_installer_instances as $instance){
|
86 |
+
|
87 |
+
if(!isset($delegate)){
|
88 |
+
$delegate = $instance;
|
89 |
+
continue;
|
90 |
+
}
|
91 |
+
|
92 |
+
if(version_compare($instance['version'], $delegate['version'], '>')){
|
93 |
+
$delegate = $instance;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
// priority based election
|
98 |
+
$highest_priority = null;
|
99 |
+
foreach($wp_installer_instances as $instance) {
|
100 |
+
if(isset($instance['args']['high_priority'])){
|
101 |
+
if(is_null($highest_priority) || $instance['args']['high_priority'] <= $highest_priority){
|
102 |
+
$highest_priority = $instance['args']['high_priority'];
|
103 |
+
$delegate = $instance;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
// Exception: When WPML prior 3.2 is used, that instance must be used regardless of another newer instance
|
109 |
+
// Case 2: WPML loaded after Types
|
110 |
+
if( defined('ICL_SITEPRESS_VERSION') && version_compare(ICL_SITEPRESS_VERSION, '3.2', '<') ) {
|
111 |
+
foreach($wp_installer_instances as $key => $instance) {
|
112 |
+
if(isset($instance['args']['site_key_nags'])){
|
113 |
+
$delegate = $instance;
|
114 |
+
$wp_installer_instances = array($key => $delegate); //Eliminate other instances
|
115 |
+
break;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
include_once $delegate['bootfile'];
|
121 |
+
|
122 |
+
// set configuration
|
123 |
+
if(strpos(realpath($delegate['bootfile']), realpath(TEMPLATEPATH)) === 0){
|
124 |
+
$delegate['args']['in_theme_folder'] = dirname(ltrim(str_replace(realpath(TEMPLATEPATH), '', realpath($delegate['bootfile'])), '\\/'));
|
125 |
+
}
|
126 |
+
if(isset($delegate['args']) && is_array($delegate['args'])){
|
127 |
+
foreach($delegate['args'] as $key => $value){
|
128 |
+
WP_Installer()->set_config($key, $value);
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
if(!function_exists('WP_Installer_Setup')){
|
136 |
+
|
137 |
+
// $args:
|
138 |
+
// plugins_install_tab = true|false (default: true)
|
139 |
+
// repositories_include = array() (default: all)
|
140 |
+
// repositories_exclude = array() (default: none)
|
141 |
+
// template = name (default: default)
|
142 |
+
//
|
143 |
+
// Ext function
|
144 |
+
function WP_Installer_Setup($wp_installer_instance, $args = array()){
|
145 |
+
global $wp_installer_instances;
|
146 |
+
|
147 |
+
$wp_installer_instances[$wp_installer_instance]['args'] = $args;
|
148 |
+
|
149 |
+
}
|
150 |
+
|
151 |
}
|
library/otgs/installer/locale/orig/installer.po
CHANGED
@@ -1,230 +1,230 @@
|
|
1 |
-
# This file was generated by WPML
|
2 |
-
# WPML is a WordPress plugin that can turn any WordPress site into a full featured multilingual content management system.
|
3 |
-
# https://wpml.org
|
4 |
-
msgid ""
|
5 |
-
msgstr ""
|
6 |
-
"Content-Type: text/plain; charset=utf-8\n"
|
7 |
-
"Content-Transfer-Encoding: 8bit\n"
|
8 |
-
"Project-Id-Version:WPML_EXPORT\n"
|
9 |
-
"POT-Creation-Date: \n"
|
10 |
-
"PO-Revision-Date: \n"
|
11 |
-
"Last-Translator: \n"
|
12 |
-
"Language-Team: \n"
|
13 |
-
"Language:en\n"
|
14 |
-
"MIME-Version: 1.0\n"
|
15 |
-
|
16 |
-
msgid "Installer"
|
17 |
-
msgstr ""
|
18 |
-
|
19 |
-
msgid "Registered"
|
20 |
-
msgstr ""
|
21 |
-
|
22 |
-
msgid "Register"
|
23 |
-
msgstr ""
|
24 |
-
|
25 |
-
msgid "To get automatic updates, you need to register %s for this site. %sRegister %s%s"
|
26 |
-
msgstr ""
|
27 |
-
|
28 |
-
msgid "Dismiss"
|
29 |
-
msgstr ""
|
30 |
-
|
31 |
-
msgid "Commercial"
|
32 |
-
msgstr ""
|
33 |
-
|
34 |
-
msgid "Installer cannot contact our updates server to get information about the available products and check for new versions. If you are seeing this message for the first time, you can ignore it, as it may be a temporary communication problem. If the problem persists and your WordPress admin is slowing down, you can disable automated version checks. Add the following line to your wp-config.php file:"
|
35 |
-
msgstr ""
|
36 |
-
|
37 |
-
msgid "No repositories defined."
|
38 |
-
msgstr ""
|
39 |
-
|
40 |
-
msgid "%s cannot access %s to register. Try again to see if it's a temporary problem. If the problem continues, make sure that this site has access to the Internet. You can still use the plugin without registration, but you will not receive automated updates."
|
41 |
-
msgstr ""
|
42 |
-
|
43 |
-
msgid "Invalid site key for the current site."
|
44 |
-
msgstr ""
|
45 |
-
|
46 |
-
msgid "You will have to renew your subscription in order to continue getting the updates and support."
|
47 |
-
msgstr ""
|
48 |
-
|
49 |
-
msgid "%sRenew here%s."
|
50 |
-
msgstr ""
|
51 |
-
|
52 |
-
msgid "Your subscription appears to no longer be valid. Please try to register again using a valid site key."
|
53 |
-
msgstr ""
|
54 |
-
|
55 |
-
msgid "You need to have a valid subscription in order to get upgrades or support for this plugin. %sPurchase a subscription or enter an existing site key%s."
|
56 |
-
msgstr ""
|
57 |
-
|
58 |
-
msgid "%s cannot update because your site's registration is not valid. Please %sregister %s%s again for this site first."
|
59 |
-
msgstr ""
|
60 |
-
|
61 |
-
msgid "Update Plugin"
|
62 |
-
msgstr ""
|
63 |
-
|
64 |
-
msgid "Return to the plugins page"
|
65 |
-
msgstr ""
|
66 |
-
|
67 |
-
msgid "Your subscription expires in %d day."
|
68 |
-
msgstr ""
|
69 |
-
|
70 |
-
msgid "Your subscription expires in %d days."
|
71 |
-
msgstr ""
|
72 |
-
|
73 |
-
msgid "Downloading is not possible because WordPress cannot write into the plugins folder. %sHow to fix%s."
|
74 |
-
msgstr ""
|
75 |
-
|
76 |
-
msgid "Plugin"
|
77 |
-
msgstr ""
|
78 |
-
|
79 |
-
msgid "downloading..."
|
80 |
-
msgstr ""
|
81 |
-
|
82 |
-
msgid "failed!"
|
83 |
-
msgstr ""
|
84 |
-
|
85 |
-
msgid "downloaded"
|
86 |
-
msgstr ""
|
87 |
-
|
88 |
-
msgid "activating"
|
89 |
-
msgstr ""
|
90 |
-
|
91 |
-
msgid "activated"
|
92 |
-
msgstr ""
|
93 |
-
|
94 |
-
msgid "Activate after download"
|
95 |
-
msgstr ""
|
96 |
-
|
97 |
-
msgid "Operation complete!"
|
98 |
-
msgstr ""
|
99 |
-
|
100 |
-
msgid "Download failed!\n\nClick OK to revalidate your subscription or CANCEL to try again."
|
101 |
-
msgstr ""
|
102 |
-
|
103 |
-
msgid "Available"
|
104 |
-
msgstr ""
|
105 |
-
|
106 |
-
msgid "Installed"
|
107 |
-
msgstr ""
|
108 |
-
|
109 |
-
msgid "Downloading"
|
110 |
-
msgstr ""
|
111 |
-
|
112 |
-
msgid "Activate"
|
113 |
-
msgstr ""
|
114 |
-
|
115 |
-
msgid "Download"
|
116 |
-
msgstr ""
|
117 |
-
|
118 |
-
msgid "Downloads:"
|
119 |
-
msgstr ""
|
120 |
-
|
121 |
-
msgid "Current version"
|
122 |
-
msgstr ""
|
123 |
-
|
124 |
-
msgid "Released"
|
125 |
-
msgstr ""
|
126 |
-
|
127 |
-
msgid "Installed version"
|
128 |
-
msgstr ""
|
129 |
-
|
130 |
-
msgid "(embedded)"
|
131 |
-
msgstr ""
|
132 |
-
|
133 |
-
msgid "installing..."
|
134 |
-
msgstr ""
|
135 |
-
|
136 |
-
msgid "updating..."
|
137 |
-
msgstr ""
|
138 |
-
|
139 |
-
msgid "installed"
|
140 |
-
msgstr ""
|
141 |
-
|
142 |
-
msgid "updated"
|
143 |
-
msgstr ""
|
144 |
-
|
145 |
-
msgid "Download failed!\n\nPlease refresh the page and try again."
|
146 |
-
msgstr ""
|
147 |
-
|
148 |
-
msgid "Incorrect setup"
|
149 |
-
msgstr ""
|
150 |
-
|
151 |
-
msgid "Invalid product"
|
152 |
-
msgstr ""
|
153 |
-
|
154 |
-
msgid "Unknown repository"
|
155 |
-
msgstr ""
|
156 |
-
|
157 |
-
msgid " Your current site key (%s) does not match the selected product (%s)."
|
158 |
-
msgstr ""
|
159 |
-
|
160 |
-
msgid "Buy %s"
|
161 |
-
msgstr ""
|
162 |
-
|
163 |
-
msgid "Already bought %s?"
|
164 |
-
msgstr ""
|
165 |
-
|
166 |
-
msgid "Renew %s"
|
167 |
-
msgstr ""
|
168 |
-
|
169 |
-
msgid "Remove current site key (%s)"
|
170 |
-
msgstr ""
|
171 |
-
|
172 |
-
msgid "%s support on wpml.org"
|
173 |
-
msgstr ""
|
174 |
-
|
175 |
-
msgid "Enter site key"
|
176 |
-
msgstr ""
|
177 |
-
|
178 |
-
msgid "Subscription is expired."
|
179 |
-
msgstr ""
|
180 |
-
|
181 |
-
msgid "Add"
|
182 |
-
msgstr ""
|
183 |
-
|
184 |
-
msgid "Are you sure you want to remove this site key?"
|
185 |
-
msgstr ""
|
186 |
-
|
187 |
-
msgid "Register %s"
|
188 |
-
msgstr ""
|
189 |
-
|
190 |
-
msgid "1. Go to your %s%s account%s and add this site URL: %s"
|
191 |
-
msgstr ""
|
192 |
-
|
193 |
-
msgid "Unregister %s from this site"
|
194 |
-
msgstr ""
|
195 |
-
|
196 |
-
msgid "%s is registered on this site. You will receive automatic updates until %s"
|
197 |
-
msgstr ""
|
198 |
-
|
199 |
-
msgid "%s is registered on this site. Your Lifetime account gives you updates for life."
|
200 |
-
msgstr ""
|
201 |
-
|
202 |
-
msgid "This page lets you install plugins and update existing plugins. To remove any of these plugins, go to the %splugins%s page and if you have the permission to remove plugins you should be able to do this."
|
203 |
-
msgstr ""
|
204 |
-
|
205 |
-
msgid "Already bought?"
|
206 |
-
msgstr ""
|
207 |
-
|
208 |
-
msgid "2. Enter your site key"
|
209 |
-
msgstr ""
|
210 |
-
|
211 |
-
msgid "Subscription is expired. You need to either purchase a new subscription or upgrade if available."
|
212 |
-
msgstr ""
|
213 |
-
|
214 |
-
msgid "Check for updates"
|
215 |
-
msgstr ""
|
216 |
-
|
217 |
-
msgid "Individual components"
|
218 |
-
msgstr ""
|
219 |
-
|
220 |
-
msgid "OK"
|
221 |
-
msgstr ""
|
222 |
-
|
223 |
-
msgid "Cancel"
|
224 |
-
msgstr ""
|
225 |
-
|
226 |
-
msgid "Are you sure you want to unregister?"
|
227 |
-
msgstr ""
|
228 |
-
|
229 |
-
msgid "Click to see individual components options."
|
230 |
-
msgstr ""
|
1 |
+
# This file was generated by WPML
|
2 |
+
# WPML is a WordPress plugin that can turn any WordPress site into a full featured multilingual content management system.
|
3 |
+
# https://wpml.org
|
4 |
+
msgid ""
|
5 |
+
msgstr ""
|
6 |
+
"Content-Type: text/plain; charset=utf-8\n"
|
7 |
+
"Content-Transfer-Encoding: 8bit\n"
|
8 |
+
"Project-Id-Version:WPML_EXPORT\n"
|
9 |
+
"POT-Creation-Date: \n"
|
10 |
+
"PO-Revision-Date: \n"
|
11 |
+
"Last-Translator: \n"
|
12 |
+
"Language-Team: \n"
|
13 |
+
"Language:en\n"
|
14 |
+
"MIME-Version: 1.0\n"
|
15 |
+
|
16 |
+
msgid "Installer"
|
17 |
+
msgstr ""
|
18 |
+
|
19 |
+
msgid "Registered"
|
20 |
+
msgstr ""
|
21 |
+
|
22 |
+
msgid "Register"
|
23 |
+
msgstr ""
|
24 |
+
|
25 |
+
msgid "To get automatic updates, you need to register %s for this site. %sRegister %s%s"
|
26 |
+
msgstr ""
|
27 |
+
|
28 |
+
msgid "Dismiss"
|
29 |
+
msgstr ""
|
30 |
+
|
31 |
+
msgid "Commercial"
|
32 |
+
msgstr ""
|
33 |
+
|
34 |
+
msgid "Installer cannot contact our updates server to get information about the available products and check for new versions. If you are seeing this message for the first time, you can ignore it, as it may be a temporary communication problem. If the problem persists and your WordPress admin is slowing down, you can disable automated version checks. Add the following line to your wp-config.php file:"
|
35 |
+
msgstr ""
|
36 |
+
|
37 |
+
msgid "No repositories defined."
|
38 |
+
msgstr ""
|
39 |
+
|
40 |
+
msgid "%s cannot access %s to register. Try again to see if it's a temporary problem. If the problem continues, make sure that this site has access to the Internet. You can still use the plugin without registration, but you will not receive automated updates."
|
41 |
+
msgstr ""
|
42 |
+
|
43 |
+
msgid "Invalid site key for the current site."
|
44 |
+
msgstr ""
|
45 |
+
|
46 |
+
msgid "You will have to renew your subscription in order to continue getting the updates and support."
|
47 |
+
msgstr ""
|
48 |
+
|
49 |
+
msgid "%sRenew here%s."
|
50 |
+
msgstr ""
|
51 |
+
|
52 |
+
msgid "Your subscription appears to no longer be valid. Please try to register again using a valid site key."
|
53 |
+
msgstr ""
|
54 |
+
|
55 |
+
msgid "You need to have a valid subscription in order to get upgrades or support for this plugin. %sPurchase a subscription or enter an existing site key%s."
|
56 |
+
msgstr ""
|
57 |
+
|
58 |
+
msgid "%s cannot update because your site's registration is not valid. Please %sregister %s%s again for this site first."
|
59 |
+
msgstr ""
|
60 |
+
|
61 |
+
msgid "Update Plugin"
|
62 |
+
msgstr ""
|
63 |
+
|
64 |
+
msgid "Return to the plugins page"
|
65 |
+
msgstr ""
|
66 |
+
|
67 |
+
msgid "Your subscription expires in %d day."
|
68 |
+
msgstr ""
|
69 |
+
|
70 |
+
msgid "Your subscription expires in %d days."
|
71 |
+
msgstr ""
|
72 |
+
|
73 |
+
msgid "Downloading is not possible because WordPress cannot write into the plugins folder. %sHow to fix%s."
|
74 |
+
msgstr ""
|
75 |
+
|
76 |
+
msgid "Plugin"
|
77 |
+
msgstr ""
|
78 |
+
|
79 |
+
msgid "downloading..."
|
80 |
+
msgstr ""
|
81 |
+
|
82 |
+
msgid "failed!"
|
83 |
+
msgstr ""
|
84 |
+
|
85 |
+
msgid "downloaded"
|
86 |
+
msgstr ""
|
87 |
+
|
88 |
+
msgid "activating"
|
89 |
+
msgstr ""
|
90 |
+
|
91 |
+
msgid "activated"
|
92 |
+
msgstr ""
|
93 |
+
|
94 |
+
msgid "Activate after download"
|
95 |
+
msgstr ""
|
96 |
+
|
97 |
+
msgid "Operation complete!"
|
98 |
+
msgstr ""
|
99 |
+
|
100 |
+
msgid "Download failed!\n\nClick OK to revalidate your subscription or CANCEL to try again."
|
101 |
+
msgstr ""
|
102 |
+
|
103 |
+
msgid "Available"
|
104 |
+
msgstr ""
|
105 |
+
|
106 |
+
msgid "Installed"
|
107 |
+
msgstr ""
|
108 |
+
|
109 |
+
msgid "Downloading"
|
110 |
+
msgstr ""
|
111 |
+
|
112 |
+
msgid "Activate"
|
113 |
+
msgstr ""
|
114 |
+
|
115 |
+
msgid "Download"
|
116 |
+
msgstr ""
|
117 |
+
|
118 |
+
msgid "Downloads:"
|
119 |
+
msgstr ""
|
120 |
+
|
121 |
+
msgid "Current version"
|
122 |
+
msgstr ""
|
123 |
+
|
124 |
+
msgid "Released"
|
125 |
+
msgstr ""
|
126 |
+
|
127 |
+
msgid "Installed version"
|
128 |
+
msgstr ""
|
129 |
+
|
130 |
+
msgid "(embedded)"
|
131 |
+
msgstr ""
|
132 |
+
|
133 |
+
msgid "installing..."
|
134 |
+
msgstr ""
|
135 |
+
|
136 |
+
msgid "updating..."
|
137 |
+
msgstr ""
|
138 |
+
|
139 |
+
msgid "installed"
|
140 |
+
msgstr ""
|
141 |
+
|
142 |
+
msgid "updated"
|
143 |
+
msgstr ""
|
144 |
+
|
145 |
+
msgid "Download failed!\n\nPlease refresh the page and try again."
|
146 |
+
msgstr ""
|
147 |
+
|
148 |
+
msgid "Incorrect setup"
|
149 |
+
msgstr ""
|
150 |
+
|
151 |
+
msgid "Invalid product"
|
152 |
+
msgstr ""
|
153 |
+
|
154 |
+
msgid "Unknown repository"
|
155 |
+
msgstr ""
|
156 |
+
|
157 |
+
msgid " Your current site key (%s) does not match the selected product (%s)."
|
158 |
+
msgstr ""
|
159 |
+
|
160 |
+
msgid "Buy %s"
|
161 |
+
msgstr ""
|
162 |
+
|
163 |
+
msgid "Already bought %s?"
|
164 |
+
msgstr ""
|
165 |
+
|
166 |
+
msgid "Renew %s"
|
167 |
+
msgstr ""
|
168 |
+
|
169 |
+
msgid "Remove current site key (%s)"
|
170 |
+
msgstr ""
|
171 |
+
|
172 |
+
msgid "%s support on wpml.org"
|
173 |
+
msgstr ""
|
174 |
+
|
175 |
+
msgid "Enter site key"
|
176 |
+
msgstr ""
|
177 |
+
|
178 |
+
msgid "Subscription is expired."
|
179 |
+
msgstr ""
|
180 |
+
|
181 |
+
msgid "Add"
|
182 |
+
msgstr ""
|
183 |
+
|
184 |
+
msgid "Are you sure you want to remove this site key?"
|
185 |
+
msgstr ""
|
186 |
+
|
187 |
+
msgid "Register %s"
|
188 |
+
msgstr ""
|
189 |
+
|
190 |
+
msgid "1. Go to your %s%s account%s and add this site URL: %s"
|
191 |
+
msgstr ""
|
192 |
+
|
193 |
+
msgid "Unregister %s from this site"
|
194 |
+
msgstr ""
|
195 |
+
|
196 |
+
msgid "%s is registered on this site. You will receive automatic updates until %s"
|
197 |
+
msgstr ""
|
198 |
+
|
199 |
+
msgid "%s is registered on this site. Your Lifetime account gives you updates for life."
|
200 |
+
msgstr ""
|
201 |
+
|
202 |
+
msgid "This page lets you install plugins and update existing plugins. To remove any of these plugins, go to the %splugins%s page and if you have the permission to remove plugins you should be able to do this."
|
203 |
+
msgstr ""
|
204 |
+
|
205 |
+
msgid "Already bought?"
|
206 |
+
msgstr ""
|
207 |
+
|
208 |
+
msgid "2. Enter your site key"
|
209 |
+
msgstr ""
|
210 |
+
|
211 |
+
msgid "Subscription is expired. You need to either purchase a new subscription or upgrade if available."
|
212 |
+
msgstr ""
|
213 |
+
|
214 |
+
msgid "Check for updates"
|
215 |
+
msgstr ""
|
216 |
+
|
217 |
+
msgid "Individual components"
|
218 |
+
msgstr ""
|
219 |
+
|
220 |
+
msgid "OK"
|
221 |
+
msgstr ""
|
222 |
+
|
223 |
+
msgid "Cancel"
|
224 |
+
msgstr ""
|
225 |
+
|
226 |
+
msgid "Are you sure you want to unregister?"
|
227 |
+
msgstr ""
|
228 |
+
|
229 |
+
msgid "Click to see individual components options."
|
230 |
+
msgstr ""
|
library/otgs/installer/repositories.xml
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
-
<?xml version="1.0" encoding="utf-8"?>
|
2 |
-
<repositories>
|
3 |
-
<repository>
|
4 |
-
<id>wpml</id>
|
5 |
-
<apiurl>https://api.wpml.org/</apiurl>
|
6 |
-
<products>http://d2salfytceyqoe.cloudfront.net/wpml33-products.json</products>
|
7 |
-
</repository>
|
8 |
-
<repository>
|
9 |
-
<id>toolset</id>
|
10 |
-
<apiurl>https://api.wp-types.com/</apiurl>
|
11 |
-
<products>http://d7j863fr5jhrr.cloudfront.net/toolset33-products.json</products>
|
12 |
-
</repository>
|
13 |
-
</repositories>
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<repositories>
|
3 |
+
<repository>
|
4 |
+
<id>wpml</id>
|
5 |
+
<apiurl>https://api.wpml.org/</apiurl>
|
6 |
+
<products>http://d2salfytceyqoe.cloudfront.net/wpml33-products.json</products>
|
7 |
+
</repository>
|
8 |
+
<repository>
|
9 |
+
<id>toolset</id>
|
10 |
+
<apiurl>https://api.wp-types.com/</apiurl>
|
11 |
+
<products>http://d7j863fr5jhrr.cloudfront.net/toolset33-products.json</products>
|
12 |
+
</repository>
|
13 |
+
</repositories>
|
library/otgs/installer/res/css/admin.css
CHANGED
@@ -1,193 +1,201 @@
|
|
1 |
-
.otgsi_site_key_form{
|
2 |
-
display:none;
|
3 |
-
/*display:inline;*/
|
4 |
-
}
|
5 |
-
|
6 |
-
.installer-status-installing, .installer-status-installed, .installer-status-updating, .installer-status-updated, .installer-status-activating, .installer-status-activated, .installer-status-success{
|
7 |
-
display: none;
|
8 |
-
}
|
9 |
-
.installer-status-installing{color: #FF9900; }
|
10 |
-
.installer-status-installed{color: #003300; font-weight: bold; }
|
11 |
-
.installer-status-updating{color: #FF9900; }
|
12 |
-
.installer-status-updated{color: #003300; font-weight: bold; }
|
13 |
-
|
14 |
-
.installer-status-activating{color: #996666 }
|
15 |
-
.installer-status-activated{color: #333366; font-weight: bold; }
|
16 |
-
|
17 |
-
.js-status-success p{
|
18 |
-
color: #FF9900;
|
19 |
-
padding: 4px;
|
20 |
-
}
|
21 |
-
|
22 |
-
.installer-green-text{
|
23 |
-
color:#006600;
|
24 |
-
font-weight:bold;
|
25 |
-
}
|
26 |
-
|
27 |
-
.installer-red-text{
|
28 |
-
color:#b22121;
|
29 |
-
font-weight:bold;
|
30 |
-
}
|
31 |
-
|
32 |
-
.installer-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
.
|
46 |
-
|
47 |
-
}
|
48 |
-
|
49 |
-
.
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
.
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
.
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
}
|
100 |
-
|
101 |
-
.
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
border:solid 1px #
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
background-color: #
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
background-color: #
|
126 |
-
}
|
127 |
-
|
128 |
-
.installer-plugins-list-compact
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
}
|
145 |
-
|
146 |
-
.otgs_wp_installer_table_compact .installer-status-
|
147 |
-
.otgs_wp_installer_table_compact .installer-status-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
.
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
}
|
165 |
-
|
166 |
-
.
|
167 |
-
|
168 |
-
}
|
169 |
-
|
170 |
-
.
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
font-style: italic;
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
.
|
189 |
-
|
190 |
-
}
|
191 |
-
|
192 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
}
|
1 |
+
.otgsi_site_key_form{
|
2 |
+
display:none;
|
3 |
+
/*display:inline;*/
|
4 |
+
}
|
5 |
+
|
6 |
+
.installer-status-installing, .installer-status-installed, .installer-status-updating, .installer-status-updated, .installer-status-activating, .installer-status-activated, .installer-status-success{
|
7 |
+
display: none;
|
8 |
+
}
|
9 |
+
.installer-status-installing{color: #FF9900; }
|
10 |
+
.installer-status-installed{color: #003300; font-weight: bold; }
|
11 |
+
.installer-status-updating{color: #FF9900; }
|
12 |
+
.installer-status-updated{color: #003300; font-weight: bold; }
|
13 |
+
|
14 |
+
.installer-status-activating{color: #996666 }
|
15 |
+
.installer-status-activated{color: #333366; font-weight: bold; }
|
16 |
+
|
17 |
+
.js-status-success p{
|
18 |
+
color: #FF9900;
|
19 |
+
padding: 4px;
|
20 |
+
}
|
21 |
+
|
22 |
+
.installer-green-text{
|
23 |
+
color:#006600;
|
24 |
+
font-weight:bold;
|
25 |
+
}
|
26 |
+
|
27 |
+
.installer-red-text{
|
28 |
+
color:#b22121;
|
29 |
+
font-weight:bold;
|
30 |
+
}
|
31 |
+
|
32 |
+
.installer-footnote{
|
33 |
+
color:#3d5e69;
|
34 |
+
display:block;
|
35 |
+
float: left;
|
36 |
+
font-style: italic;
|
37 |
+
font-size: 90%;
|
38 |
+
}
|
39 |
+
|
40 |
+
.installer-products-list li{
|
41 |
+
display: inline;
|
42 |
+
margin-right: 20px;
|
43 |
+
}
|
44 |
+
|
45 |
+
.otgs_wp_installer_table a.disabled{
|
46 |
+
color:#888;
|
47 |
+
}
|
48 |
+
|
49 |
+
.otgs_wp_installer_subtable{
|
50 |
+
clear: both;
|
51 |
+
margin-left:-20px;
|
52 |
+
}
|
53 |
+
.otgs_wp_installer_subtable td p{
|
54 |
+
font-size: 92%;
|
55 |
+
}
|
56 |
+
|
57 |
+
.installer-status-error{
|
58 |
+
color: #f00;
|
59 |
+
}
|
60 |
+
|
61 |
+
.installer-status-note{
|
62 |
+
color: #6F6E6D;
|
63 |
+
font-style: italic;
|
64 |
+
}
|
65 |
+
|
66 |
+
.installer-warn-box{
|
67 |
+
-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;border:1px solid #962722;background-color:#F5C8C6;
|
68 |
+
color: #333;
|
69 |
+
padding: 5px;
|
70 |
+
}
|
71 |
+
.installer-warn-box span.details{
|
72 |
+
font-style: italic;
|
73 |
+
color:#777;
|
74 |
+
}
|
75 |
+
|
76 |
+
.installer-error-box{
|
77 |
+
color:#962722;
|
78 |
+
margin-top: 10px;
|
79 |
+
}
|
80 |
+
.installer-error-box p{
|
81 |
+
margin: 10px 0 10px 0;
|
82 |
+
-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;border:1px solid #962722;background-color:#F5C8C6;
|
83 |
+
color: #333;
|
84 |
+
padding: 5px;
|
85 |
+
text-align: center;
|
86 |
+
}
|
87 |
+
|
88 |
+
.spinner-inline{
|
89 |
+
float: none;
|
90 |
+
display: inline-block;
|
91 |
+
visibility: visible;
|
92 |
+
}
|
93 |
+
|
94 |
+
.installer-q-icon:before{
|
95 |
+
content: '\f223' !important;
|
96 |
+
font-family: dashicons !important;
|
97 |
+
color: #f56e28;
|
98 |
+
font: 20px/1 "dashicons";
|
99 |
+
}
|
100 |
+
|
101 |
+
.installer-plugin-update-tr td{
|
102 |
+
padding-left:3px !important;
|
103 |
+
}
|
104 |
+
|
105 |
+
.otgsi_yellow_bg{
|
106 |
+
background-color: #f2f46b;
|
107 |
+
}
|
108 |
+
|
109 |
+
.otgs_wp_installer_table_compact{
|
110 |
+
width:480px;
|
111 |
+
border: solid 1px #999;
|
112 |
+
padding:10px;
|
113 |
+
border-radius: 5px;
|
114 |
+
}
|
115 |
+
|
116 |
+
.installer-plugins-list-compact{
|
117 |
+
background-color: #fff;
|
118 |
+
border-collapse: collapse;
|
119 |
+
border:solid 1px #C1DAD7;
|
120 |
+
width:100%;
|
121 |
+
}
|
122 |
+
|
123 |
+
.installer-plugins-list-compact tr th{
|
124 |
+
padding-top:3px;
|
125 |
+
background-color: #ccc;
|
126 |
+
}
|
127 |
+
|
128 |
+
.installer-plugins-list-compact tr{
|
129 |
+
background-color: #ddd;
|
130 |
+
}
|
131 |
+
|
132 |
+
.installer-plugins-list-compact tr.even{
|
133 |
+
background-color: #eee;
|
134 |
+
}
|
135 |
+
|
136 |
+
.installer-plugins-list-compact td{
|
137 |
+
padding:2px 5px 2px 5px;
|
138 |
+
border-right: 1px solid #C1DAD7;
|
139 |
+
border-bottom: 1px solid #C1DAD7;
|
140 |
+
}
|
141 |
+
|
142 |
+
.installer-plugins-list-compact td.twelve{
|
143 |
+
width:16px;
|
144 |
+
}
|
145 |
+
|
146 |
+
.otgs_wp_installer_table_compact .installer-status-downloading,
|
147 |
+
.otgs_wp_installer_table_compact .installer-status-downloaded,
|
148 |
+
.otgs_wp_installer_table_compact .installer-status-activating,
|
149 |
+
.otgs_wp_installer_table_compact .installer-status-activated{
|
150 |
+
display: none;
|
151 |
+
color:transparent; width: 12px; padding:2px;
|
152 |
+
}
|
153 |
+
|
154 |
+
.otgs_wp_installer_table_compact .installer-status-success,
|
155 |
+
.otgs_wp_installer_table_compact .installer-status-fail{
|
156 |
+
display: none;
|
157 |
+
}
|
158 |
+
|
159 |
+
.installer-status-success{
|
160 |
+
float: right;
|
161 |
+
color: #006600;
|
162 |
+
}
|
163 |
+
|
164 |
+
.otgs_wp_installer_table_compact .installer-status-downloading{background: url(../img/dn.gif) no-repeat center; }
|
165 |
+
.otgs_wp_installer_table_compact .installer-status-downloaded{background: url(../img/complete.png) no-repeat center;}
|
166 |
+
.otgs_wp_installer_table_compact .installer-status-activating{background: url(../img/dn.gif) no-repeat center; }
|
167 |
+
.otgs_wp_installer_table_compact .installer-status-activated{background: url(../img/complete.png) no-repeat center; }
|
168 |
+
.otgs_wp_installer_table_compact .installer-status-error{background: url(../img/icon_error.gif) no-repeat center; }
|
169 |
+
|
170 |
+
.installer_highlight{
|
171 |
+
color:#c5510b;
|
172 |
+
}
|
173 |
+
|
174 |
+
.installer_highlight_package{
|
175 |
+
background-color: #fff9c0;
|
176 |
+
}
|
177 |
+
|
178 |
+
.plugin_progress{
|
179 |
+
font-style: italic;
|
180 |
+
color: #777
|
181 |
+
}
|
182 |
+
|
183 |
+
.installer-download-progress-status{
|
184 |
+
display: none;
|
185 |
+
float:right;
|
186 |
+
color: #006600;
|
187 |
+
font-style: italic;
|
188 |
+
background: url('../img/spinner.gif') no-repeat;
|
189 |
+
padding-left:24px;
|
190 |
+
}
|
191 |
+
|
192 |
+
.otgs-is-dismissible {
|
193 |
+
position: relative;
|
194 |
+
padding-right: 38px;
|
195 |
+
}
|
196 |
+
.otgs-is-dismissible .notice-dismiss {
|
197 |
+
text-decoration: none;
|
198 |
+
}
|
199 |
+
.otgs-is-dismissible p [class*="button-"] {
|
200 |
+
margin: -5px 5px;
|
201 |
}
|
library/otgs/installer/res/js/admin.js
CHANGED
@@ -1,403 +1,417 @@
|
|
1 |
-
var otgs_wp_installer = {
|
2 |
-
|
3 |
-
init: function(){
|
4 |
-
|
5 |
-
jQuery('.otgs_wp_installer_table').on('click', '.enter_site_key_js', otgs_wp_installer.show_site_key_form);
|
6 |
-
jQuery('.otgs_wp_installer_table').on('click', '.cancel_site_key_js', otgs_wp_installer.hide_site_key_form);
|
7 |
-
|
8 |
-
jQuery('.otgs_wp_installer_table').on('click', '.remove_site_key_js', otgs_wp_installer.remove_site_key);
|
9 |
-
jQuery('.otgs_wp_installer_table').on('click', '.update_site_key_js', otgs_wp_installer.update_site_key);
|
10 |
-
|
11 |
-
jQuery('.otgs_wp_installer_table').on('submit', '.otgsi_site_key_form', otgs_wp_installer.save_site_key);
|
12 |
-
jQuery('.otgs_wp_installer_table').on('submit', '.otgsi_downloads_form', otgs_wp_installer.download_downloads);
|
13 |
-
jQuery('.otgs_wp_installer_table').on('change', '.otgsi_downloads_form :checkbox[name="downloads[]"]', otgs_wp_installer.update_downloads_form);
|
14 |
-
|
15 |
-
jQuery('.installer-dismiss-nag').click(otgs_wp_installer.dismiss_nag);
|
16 |
-
|
17 |
-
jQuery('.otgs_wp_installer_table').on('click', '.installer_expand_button', otgs_wp_installer.toggle_subpackages);
|
18 |
-
|
19 |
-
otgs_wp_installer.scroll_to_repository();
|
20 |
-
|
21 |
-
if( typeof pagenow != 'undefined' && pagenow == 'plugins'){
|
22 |
-
|
23 |
-
jQuery(document).ajaxSuccess(function(event, xhr, settings) {
|
24 |
-
var data = otgs_wp_installer.getQueryParameters(settings.data);
|
25 |
-
if(typeof data.action != 'undefined' && data.action == 'update-plugin'){
|
26 |
-
response = xhr.responseJSON.data;
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
form.
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
form
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
thisf.
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
function
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
var
|
228 |
-
}
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
}
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
var
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
},
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
jQuery(document).ready(otgs_wp_installer.init);
|
1 |
+
var otgs_wp_installer = {
|
2 |
+
|
3 |
+
init: function(){
|
4 |
+
|
5 |
+
jQuery('.otgs_wp_installer_table').on('click', '.enter_site_key_js', otgs_wp_installer.show_site_key_form);
|
6 |
+
jQuery('.otgs_wp_installer_table').on('click', '.cancel_site_key_js', otgs_wp_installer.hide_site_key_form);
|
7 |
+
|
8 |
+
jQuery('.otgs_wp_installer_table').on('click', '.remove_site_key_js', otgs_wp_installer.remove_site_key);
|
9 |
+
jQuery('.otgs_wp_installer_table').on('click', '.update_site_key_js', otgs_wp_installer.update_site_key);
|
10 |
+
|
11 |
+
jQuery('.otgs_wp_installer_table').on('submit', '.otgsi_site_key_form', otgs_wp_installer.save_site_key);
|
12 |
+
jQuery('.otgs_wp_installer_table').on('submit', '.otgsi_downloads_form', otgs_wp_installer.download_downloads);
|
13 |
+
jQuery('.otgs_wp_installer_table').on('change', '.otgsi_downloads_form :checkbox[name="downloads[]"]', otgs_wp_installer.update_downloads_form);
|
14 |
+
|
15 |
+
jQuery('.installer-dismiss-nag').click(otgs_wp_installer.dismiss_nag);
|
16 |
+
|
17 |
+
jQuery('.otgs_wp_installer_table').on('click', '.installer_expand_button', otgs_wp_installer.toggle_subpackages);
|
18 |
+
|
19 |
+
otgs_wp_installer.scroll_to_repository();
|
20 |
+
|
21 |
+
if( typeof pagenow != 'undefined' && pagenow == 'plugins'){
|
22 |
+
|
23 |
+
jQuery(document).ajaxSuccess(function(event, xhr, settings) {
|
24 |
+
var data = otgs_wp_installer.getQueryParameters(settings.data);
|
25 |
+
if(typeof data.action != 'undefined' && data.action == 'update-plugin'){
|
26 |
+
response = xhr.responseJSON.data;
|
27 |
+
if(typeof response.error != 'undefined'){
|
28 |
+
var default_error = jQuery('#' + response.slug + '-update .update-message').html();
|
29 |
+
jQuery('#' + response.slug + '-update .update-message').html(default_error + ' »<span class="installer-red-text"> ' + response.error + '</span>');
|
30 |
+
}
|
31 |
+
}
|
32 |
+
return false;
|
33 |
+
});
|
34 |
+
|
35 |
+
}
|
36 |
+
|
37 |
+
},
|
38 |
+
|
39 |
+
getQueryParameters : function(str) {
|
40 |
+
return (str || document.location.search).replace(/(^\?)/,'').split("&").map(function(n){return n = n.split("="),this[n[0]] = n[1],this}.bind({}))[0];
|
41 |
+
},
|
42 |
+
|
43 |
+
reset_errors: function(){
|
44 |
+
jQuery('.installer-error-box').html('').hide();
|
45 |
+
},
|
46 |
+
|
47 |
+
show_error: function(repo, text){
|
48 |
+
jQuery('#installer_repo_' + repo).find('.installer-error-box').html(text).show();
|
49 |
+
},
|
50 |
+
|
51 |
+
show_site_key_form: function(){
|
52 |
+
|
53 |
+
if( jQuery(this).hasClass('disabled') ) {
|
54 |
+
alert( jQuery(this).attr('title') );
|
55 |
+
return false;
|
56 |
+
}
|
57 |
+
|
58 |
+
otgs_wp_installer.reset_errors();
|
59 |
+
|
60 |
+
var form = jQuery(this).parent().find('form.otgsi_site_key_form');
|
61 |
+
jQuery(this).prev().hide();
|
62 |
+
jQuery(this).hide();
|
63 |
+
form.css('display', 'inline');
|
64 |
+
form.find('input[name^=site_key_]').focus().val('');
|
65 |
+
form.find('input').removeAttr('disabled');
|
66 |
+
|
67 |
+
form.closest('.otgsi_register_product_wrap').addClass('otgsi_yellow_bg');
|
68 |
+
|
69 |
+
return false;
|
70 |
+
},
|
71 |
+
|
72 |
+
hide_site_key_form: function(){
|
73 |
+
var form = jQuery(this).closest('form');
|
74 |
+
form.hide();
|
75 |
+
form.parent().find('.enter_site_key_js').show();
|
76 |
+
form.parent().find('.enter_site_key_js').prev().show();
|
77 |
+
|
78 |
+
form.closest('.otgsi_register_product_wrap').removeClass('otgsi_yellow_bg');
|
79 |
+
otgs_wp_installer.reset_errors();
|
80 |
+
return false;
|
81 |
+
},
|
82 |
+
|
83 |
+
save_site_key: function(){
|
84 |
+
|
85 |
+
var thisf = jQuery(this);
|
86 |
+
var data = jQuery(this).serialize();
|
87 |
+
jQuery(this).find('input').attr('disabled', 'disabled');
|
88 |
+
|
89 |
+
var spinner = jQuery('<span class="spinner"></span>');
|
90 |
+
spinner.css({display: 'inline-block', float: 'none'}).prependTo(jQuery(this));
|
91 |
+
|
92 |
+
otgs_wp_installer.reset_errors();
|
93 |
+
|
94 |
+
jQuery.ajax({url: ajaxurl, type: 'POST', dataType:'json', data: data, success:
|
95 |
+
function(ret){
|
96 |
+
if(!ret.error){
|
97 |
+
otgs_wp_installer.saved_site_key();
|
98 |
+
}else{
|
99 |
+
otgs_wp_installer.show_error(thisf.find('[name=repository_id]').val(), ret.error);
|
100 |
+
thisf.find('input').removeAttr('disabled');
|
101 |
+
}
|
102 |
+
|
103 |
+
if(typeof ret.debug != 'undefined'){
|
104 |
+
thisf.append('<textarea style="width:100%" rows="20">' + ret.debug + '</textarea>');
|
105 |
+
}
|
106 |
+
|
107 |
+
spinner.remove();
|
108 |
+
}
|
109 |
+
});
|
110 |
+
|
111 |
+
return false;
|
112 |
+
|
113 |
+
},
|
114 |
+
|
115 |
+
saved_site_key: function(){
|
116 |
+
location.reload();
|
117 |
+
},
|
118 |
+
|
119 |
+
remove_site_key: function(){
|
120 |
+
|
121 |
+
if( jQuery(this).attr('disabled') == 'disabled' ){
|
122 |
+
|
123 |
+
alert( jQuery(this).attr('title') );
|
124 |
+
return false;
|
125 |
+
|
126 |
+
} else {
|
127 |
+
|
128 |
+
if(confirm(jQuery(this).data('confirmation'))){
|
129 |
+
|
130 |
+
jQuery('<span class="spinner"></span>').css({visibility: 'visible', float: 'none'}).prependTo(jQuery(this).parent());
|
131 |
+
data = {action: 'remove_site_key', repository_id: jQuery(this).data('repository'), nonce: jQuery(this).data('nonce')}
|
132 |
+
jQuery.ajax({url: ajaxurl, type: 'POST', data: data, success: otgs_wp_installer.removed_site_key});
|
133 |
+
}
|
134 |
+
|
135 |
+
}
|
136 |
+
|
137 |
+
return false;
|
138 |
+
},
|
139 |
+
|
140 |
+
removed_site_key: function(){
|
141 |
+
location.reload();
|
142 |
+
},
|
143 |
+
|
144 |
+
update_site_key: function(){
|
145 |
+
var error_wrap = jQuery(this).closest('.otgsi_register_product_wrap').find('.installer-error-box');
|
146 |
+
error_wrap.html('');
|
147 |
+
|
148 |
+
var spinner = jQuery('<span class="spinner"></span>');
|
149 |
+
|
150 |
+
spinner.css({visibility: 'visible', float: 'none'}).prependTo(jQuery(this).parent());
|
151 |
+
data = {action: 'update_site_key', repository_id: jQuery(this).data('repository'), nonce: jQuery(this).data('nonce')}
|
152 |
+
jQuery.ajax({
|
153 |
+
url: ajaxurl,
|
154 |
+
type: 'POST',
|
155 |
+
data: data,
|
156 |
+
dataType: 'json',
|
157 |
+
complete: function( event, xhr, settings ){
|
158 |
+
var error = '';
|
159 |
+
if(xhr == 'success') {
|
160 |
+
var ret = event.responseJSON;
|
161 |
+
if(ret.error){
|
162 |
+
error = ret.error;
|
163 |
+
}else{
|
164 |
+
otgs_wp_installer.updated_site_key(ret);
|
165 |
+
}
|
166 |
+
}else{
|
167 |
+
error = 'Error processing request (' + xhr + '). Please try again!';
|
168 |
+
}
|
169 |
+
|
170 |
+
if( error ){
|
171 |
+
error_wrap.html('<p>' + error + '</p>').show();
|
172 |
+
spinner.remove();
|
173 |
+
}
|
174 |
+
|
175 |
+
}
|
176 |
+
});
|
177 |
+
|
178 |
+
return false;
|
179 |
+
|
180 |
+
},
|
181 |
+
|
182 |
+
updated_site_key: function(ret){
|
183 |
+
location.reload();
|
184 |
+
},
|
185 |
+
|
186 |
+
update_downloads_form: function(){
|
187 |
+
|
188 |
+
var checked = jQuery('.otgsi_downloads_form :checkbox:checked[name="downloads[]"]').length;
|
189 |
+
|
190 |
+
if(checked){
|
191 |
+
jQuery(this).closest('form').find(':submit, :checkbox[name=activate]').removeAttr('disabled');
|
192 |
+
}else{
|
193 |
+
jQuery(this).closest('form').find(':submit, :checkbox[name=activate]').attr('disabled', 'disabled');
|
194 |
+
}
|
195 |
+
|
196 |
+
|
197 |
+
},
|
198 |
+
|
199 |
+
download_downloads: function(){
|
200 |
+
|
201 |
+
var activate = jQuery(this).find(":checkbox:checked[name=activate]").val(),
|
202 |
+
action_button = jQuery(this).find('input[type="submit"]');
|
203 |
+
downloads_form = jQuery(this),
|
204 |
+
idx = 0,
|
205 |
+
checkboxes = [];
|
206 |
+
|
207 |
+
jQuery(this).find(':checkbox:checked[name="downloads[]"]').each(function(){
|
208 |
+
if(jQuery(this).attr('disabled')) return;
|
209 |
+
checkboxes[idx] = jQuery(this);
|
210 |
+
idx++;
|
211 |
+
jQuery(this).attr('disabled', 'disabled');
|
212 |
+
});
|
213 |
+
|
214 |
+
idx = 0;
|
215 |
+
|
216 |
+
if( typeof checkboxes[idx] != 'undefined' ){
|
217 |
+
download_and_activate( checkboxes[idx] );
|
218 |
+
action_button.attr('disabled', 'disabled');
|
219 |
+
}
|
220 |
+
|
221 |
+
function download_and_activate( elem ){
|
222 |
+
|
223 |
+
var this_tr = elem.closest('tr');
|
224 |
+
var is_update = this_tr.find('.installer-red-text').length;
|
225 |
+
if(is_update){
|
226 |
+
var installing = this_tr.find('.installer-status-updating');
|
227 |
+
var installed = this_tr.find('.installer-status-updated');
|
228 |
+
}else{
|
229 |
+
var installing = this_tr.find('.installer-status-installing');
|
230 |
+
var installed = this_tr.find('.installer-status-installed');
|
231 |
+
|
232 |
+
}
|
233 |
+
if(activate){
|
234 |
+
var activating = this_tr.find('.installer-status-activating');
|
235 |
+
var activated = this_tr.find('.installer-status-activated');
|
236 |
+
}
|
237 |
+
|
238 |
+
if( this_tr.find('.for_spinner_js .spinner').length > 0 ){
|
239 |
+
var spinner = this_tr.find('.for_spinner_js .spinner');
|
240 |
+
}else{
|
241 |
+
var spinner = this_tr.find('.installer-status-downloading');
|
242 |
+
}
|
243 |
+
|
244 |
+
otgs_wp_installer.reset_errors();
|
245 |
+
downloads_form.find('div.installer-status-success').hide();
|
246 |
+
spinner.css('visibility', 'visible');
|
247 |
+
installing.show();
|
248 |
+
|
249 |
+
var plugin_name = this_tr.find('.installer_plugin_name').html();
|
250 |
+
if(is_update){
|
251 |
+
otgs_wp_installer.show_download_progress_status(downloads_form, installer_strings.updating.replace('%s', plugin_name));
|
252 |
+
}else{
|
253 |
+
otgs_wp_installer.show_download_progress_status(downloads_form, installer_strings.installing.replace('%s', plugin_name));
|
254 |
+
}
|
255 |
+
|
256 |
+
|
257 |
+
data = {action: 'installer_download_plugin', data: elem.val(), activate: activate}
|
258 |
+
|
259 |
+
jQuery.ajax({
|
260 |
+
url: ajaxurl,
|
261 |
+
type: 'POST',
|
262 |
+
dataType: 'json',
|
263 |
+
data: data,
|
264 |
+
success: function(ret){
|
265 |
+
installing.hide();
|
266 |
+
|
267 |
+
if(!ret.success){
|
268 |
+
installed.addClass('installer-status-error');
|
269 |
+
installed.html(installed.data('fail'));
|
270 |
+
|
271 |
+
if(ret.message){
|
272 |
+
installed.closest('.otgs_wp_installer_table').find('.installer-error-box').html('<p>' + ret.message + '</p>').show();
|
273 |
+
}else{
|
274 |
+
installed.closest('.otgs_wp_installer_table').find('.installer-error-box').html('<p>' + downloads_form.find('.installer-revalidate-message').html() + '</p>').show();
|
275 |
+
}
|
276 |
+
|
277 |
+
|
278 |
+
}
|
279 |
+
|
280 |
+
installed.show();
|
281 |
+
spinner.fadeOut();
|
282 |
+
|
283 |
+
if(ret.version){
|
284 |
+
this_tr.find('.installer_version_installed').html('<span class="installer-green-text">' + ret.version + '</span>');
|
285 |
+
}
|
286 |
+
|
287 |
+
if(ret.success && activate){
|
288 |
+
|
289 |
+
otgs_wp_installer.show_download_progress_status(downloads_form, installer_strings.activating.replace('%s', plugin_name));
|
290 |
+
activating.show();
|
291 |
+
spinner.show();
|
292 |
+
this_tr.find('.installer-red-text').removeClass('installer-red-text').addClass('installer-green-text').html(ret.version);
|
293 |
+
|
294 |
+
jQuery.ajax({
|
295 |
+
url: ajaxurl,
|
296 |
+
type: 'POST',
|
297 |
+
dataType: 'json',
|
298 |
+
data: {action: 'installer_activate_plugin', plugin_id: ret.plugin_id, nonce: ret.nonce},
|
299 |
+
success: function(ret){
|
300 |
+
activating.hide();
|
301 |
+
if(!ret.error ){
|
302 |
+
activated.show();
|
303 |
+
}
|
304 |
+
|
305 |
+
spinner.fadeOut();
|
306 |
+
|
307 |
+
idx++;
|
308 |
+
if( typeof checkboxes[idx] != 'undefined' ){
|
309 |
+
download_and_activate( checkboxes[idx] );
|
310 |
+
}else{
|
311 |
+
otgs_wp_installer.hide_download_progress_status(downloads_form);
|
312 |
+
downloads_form.find('div.installer-status-success').show();
|
313 |
+
action_button.removeAttr('disabled');
|
314 |
+
}
|
315 |
+
}
|
316 |
+
});
|
317 |
+
}else{
|
318 |
+
idx++;
|
319 |
+
if( typeof checkboxes[idx] != 'undefined' ){
|
320 |
+
download_and_activate( checkboxes[idx] );
|
321 |
+
}else{
|
322 |
+
otgs_wp_installer.hide_download_progress_status(downloads_form);
|
323 |
+
downloads_form.find('div.installer-status-success').show();
|
324 |
+
action_button.removeAttr('disabled');
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
});
|
330 |
+
|
331 |
+
};
|
332 |
+
|
333 |
+
return false;
|
334 |
+
},
|
335 |
+
|
336 |
+
|
337 |
+
show_download_progress_status: function(downloads_form, text){
|
338 |
+
|
339 |
+
downloads_form.find('.installer-download-progress-status').html(text).fadeIn();
|
340 |
+
|
341 |
+
},
|
342 |
+
|
343 |
+
hide_download_progress_status: function(downloads_form){
|
344 |
+
|
345 |
+
downloads_form.find('.installer-download-progress-status').html('').fadeOut();
|
346 |
+
|
347 |
+
},
|
348 |
+
|
349 |
+
dismiss_nag: function(){
|
350 |
+
|
351 |
+
var thisa = jQuery(this);
|
352 |
+
|
353 |
+
data = {action: 'installer_dismiss_nag', repository: jQuery(this).data('repository')}
|
354 |
+
|
355 |
+
jQuery.ajax({url: ajaxurl, type: 'POST', dataType:'json', data: data, success:
|
356 |
+
function(ret){
|
357 |
+
thisa.closest('.otgs-is-dismissible').remove();
|
358 |
+
}
|
359 |
+
});
|
360 |
+
|
361 |
+
return false;
|
362 |
+
},
|
363 |
+
|
364 |
+
toggle_subpackages: function(){
|
365 |
+
var list = jQuery(this).closest('td').find('.otgs_wp_installer_subtable');
|
366 |
+
|
367 |
+
if(list.is(':visible')){
|
368 |
+
list.slideUp('fast');
|
369 |
+
}else{
|
370 |
+
list.slideDown('fast');
|
371 |
+
}
|
372 |
+
|
373 |
+
|
374 |
+
return false;
|
375 |
+
|
376 |
+
},
|
377 |
+
|
378 |
+
scroll_to_repository: function(){
|
379 |
+
|
380 |
+
var ref = window.location.hash.replace('#', '');
|
381 |
+
|
382 |
+
if(ref) {
|
383 |
+
var split = ref.split('/');
|
384 |
+
var repo = split[0];
|
385 |
+
|
386 |
+
if(typeof split[1] != 'undefined'){
|
387 |
+
var package = split[1];
|
388 |
+
var repo_element = jQuery('#repository-' + repo);
|
389 |
+
|
390 |
+
|
391 |
+
|
392 |
+
if(repo_element.length){
|
393 |
+
|
394 |
+
jQuery('html, body').animate({
|
395 |
+
scrollTop: repo_element.offset().top
|
396 |
+
}, 1000);
|
397 |
+
|
398 |
+
var package_element = jQuery('#repository-' + repo +'_' + package);
|
399 |
+
|
400 |
+
if(package_element.length && !package_element.is(':visible')){
|
401 |
+
package_element.parents('.otgs_wp_installer_subtable').slideDown();
|
402 |
+
package_element.addClass('installer_highlight_package');
|
403 |
+
}
|
404 |
+
|
405 |
+
package_element.find('.button-secondary').removeClass('button-secondary').addClass('button-primary');
|
406 |
+
}
|
407 |
+
}
|
408 |
+
|
409 |
+
}
|
410 |
+
|
411 |
+
}
|
412 |
+
|
413 |
+
|
414 |
+
}
|
415 |
+
|
416 |
+
|
417 |
jQuery(document).ready(otgs_wp_installer.init);
|
library/otgs/installer/res/js/iframeResizer.min.js
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
/*! iFrame Resizer (iframeSizer.min.js ) - v2.6.1 - 2014-09-03
|
2 |
-
* Desc: Force cross domain iframes to size to content.
|
3 |
-
* Requires: iframeResizer.contentWindow.min.js to be loaded into the target frame.
|
4 |
-
* Copyright: (c) 2014 David J. Bradshaw - dave@bradshaw.net
|
5 |
-
* License: MIT
|
6 |
-
*/
|
7 |
-
|
8 |
-
!function(){"use strict";function a(a,b,c){"addEventListener"in window?a.addEventListener(b,c,!1):"attachEvent"in window&&a.attachEvent("on"+b,c)}function b(){var a,b=["moz","webkit","o","ms"];for(a=0;a<b.length&&!w;a+=1)w=window[b[a]+"RequestAnimationFrame"];w||c(" RequestAnimationFrame not supported")}function c(a){y.log&&"object"==typeof console&&console.log(s+"[Host page"+u+"]"+a)}function d(a){function b(){function a(){h(z),f(),y.resizedCallback(z)}i(a,z,"resetPage")}function d(a){var b=a.id;c(" Removing iFrame: "+b),a.parentNode.removeChild(a),y.closedCallback(b),c(" --")}function e(){var a=x.substr(t).split(":");return{iframe:document.getElementById(a[0]),id:a[0],height:a[1],width:a[2],type:a[3]}}function j(a){var b=Number(y["max"+a]),d=Number(y["min"+a]),e=a.toLowerCase(),f=Number(z[e]);if(d>b)throw new Error("Value for min"+a+" can not be greater than max"+a);c(" Checking "+e+" is in range "+d+"-"+b),d>f&&(f=d,c(" Set "+e+" to min value")),f>b&&(f=b,c(" Set "+e+" to max value")),z[e]=""+f}function k(){var b=a.origin,d=z.iframe.src.split("/").slice(0,3).join("/");if(y.checkOrigin&&(c(" Checking connection is from: "+d),""+b!="null"&&b!==d))throw new Error("Unexpected message received from: "+b+" for "+z.iframe.id+". Message was: "+a.data+". This error can be disabled by adding the checkOrigin: false option.");return!0}function l(){return s===(""+x).substr(0,t)}function m(){var a=z.type in{"true":1,"false":1};return a&&c(" Ignoring init message from meta parent page"),a}function n(){var a=x.substr(x.indexOf(":")+r+6);c(" MessageCallback passed: {iframe: "+z.iframe.id+", message: "+a+"}"),y.messageCallback({iframe:z.iframe,message:a}),c(" --")}function o(){if(null===z.iframe)throw new Error("iFrame ("+z.id+") does not exist on "+u);return!0}function q(){c(" Reposition requested from iFrame"),v={x:z.width,y:z.height},f()}function w(){switch(z.type){case"close":d(z.iframe),y.resizedCallback(z);break;case"message":n();break;case"scrollTo":q();break;case"reset":g(z);break;case"init":b(),y.initCallback(z.iframe);break;default:b()}}var x=a.data,z={};l()&&(c(" Received: "+x),z=e(),j("Height"),j("Width"),!m()&&o()&&k()&&(w(),p=!1))}function e(){null===v&&(v={x:void 0!==window.pageXOffset?window.pageXOffset:document.documentElement.scrollLeft,y:void 0!==window.pageYOffset?window.pageYOffset:document.documentElement.scrollTop},c(" Get position: "+v.x+","+v.y))}function f(){null!==v&&(window.scrollTo(v.x,v.y),c(" Set position: "+v.x+","+v.y),v=null)}function g(a){function b(){h(a),j("reset","reset",a.iframe)}c(" Size reset requested by "+("init"===a.type?"host page":"iFrame")),e(),i(b,a,"init")}function h(a){function b(b){a.iframe.style[b]=a[b]+"px",c(" IFrame ("+a.iframe.id+") "+b+" set to "+a[b]+"px")}y.sizeHeight&&b("height"),y.sizeWidth&&b("width")}function i(a,b,d){d!==b.type&&w?(c(" Requesting animation frame"),w(a)):a()}function j(a,b,d){c("["+a+"] Sending msg to iframe ("+b+")"),d.contentWindow.postMessage(s+b,"*")}function k(){function b(){function a(a){1/0!==y[a]&&0!==y[a]&&(k.style[a]=y[a]+"px",c(" Set "+a+" = "+y[a]+"px"))}a("maxHeight"),a("minHeight"),a("maxWidth"),a("minWidth")}function d(a){return""===a&&(k.id=a="iFrameResizer"+o++,c(" Added missing iframe ID: "+a+" ("+k.src+")")),a}function e(){c(" IFrame scrolling "+(y.scrolling?"enabled":"disabled")+" for "+l),k.style.overflow=!1===y.scrolling?"hidden":"auto",k.scrolling=!1===y.scrolling?"no":"yes"}function f(){("number"==typeof y.bodyMargin||"0"===y.bodyMargin)&&(y.bodyMarginV1=y.bodyMargin,y.bodyMargin=""+y.bodyMargin+"px")}function h(){return l+":"+y.bodyMarginV1+":"+y.sizeWidth+":"+y.log+":"+y.interval+":"+y.enablePublicMethods+":"+y.autoResize+":"+y.bodyMargin+":"+y.heightCalculationMethod+":"+y.bodyBackground+":"+y.bodyPadding+":"+y.tolerance}function i(b){a(k,"load",function(){var a=p;j("iFrame.onload",b,k),!a&&y.heightCalculationMethod in x&&g({iframe:k,height:0,width:0,type:"init"})}),j("init",b,k)}var k=this,l=d(k.id);e(),b(),f(),i(h())}function l(a){if("object"!=typeof a)throw new TypeError("Options is not an object.")}function m(){function a(a){if("IFRAME"!==a.tagName.toUpperCase())throw new TypeError("Expected <IFRAME> tag, found <"+a.tagName+">.");k.call(a)}function b(a){a=a||{},l(a);for(var b in z)z.hasOwnProperty(b)&&(y[b]=a.hasOwnProperty(b)?a[b]:z[b])}return function(c,d){b(c),Array.prototype.forEach.call(document.querySelectorAll(d||"iframe"),a)}}function n(a){a.fn.iFrameResize=function(b){return b=b||{},l(b),y=a.extend({},z,b),this.filter("iframe").each(k).end()}}var o=0,p=!0,q="message",r=q.length,s="[iFrameSizer]",t=s.length,u="",v=null,w=window.requestAnimationFrame,x={max:1,scroll:1,bodyScroll:1,documentElementScroll:1},y={},z={autoResize:!0,bodyBackground:null,bodyMargin:null,bodyMarginV1:8,bodyPadding:null,checkOrigin:!0,enablePublicMethods:!1,heightCalculationMethod:"offset",interval:32,log:!1,maxHeight:1/0,maxWidth:1/0,minHeight:0,minWidth:0,scrolling:!1,sizeHeight:!0,sizeWidth:!1,tolerance:0,closedCallback:function(){},initCallback:function(){},messageCallback:function(){},resizedCallback:function(){}};b(),a(window,"message",d),"jQuery"in window&&n(jQuery),"function"==typeof define&&define.amd?define(function(){return m()}):window.iFrameResize=m()}();
|
9 |
-
//# sourceMappingURL=../src/iframeResizer.map
|
10 |
-
|
1 |
+
/*! iFrame Resizer (iframeSizer.min.js ) - v2.6.1 - 2014-09-03
|
2 |
+
* Desc: Force cross domain iframes to size to content.
|
3 |
+
* Requires: iframeResizer.contentWindow.min.js to be loaded into the target frame.
|
4 |
+
* Copyright: (c) 2014 David J. Bradshaw - dave@bradshaw.net
|
5 |
+
* License: MIT
|
6 |
+
*/
|
7 |
+
|
8 |
+
!function(){"use strict";function a(a,b,c){"addEventListener"in window?a.addEventListener(b,c,!1):"attachEvent"in window&&a.attachEvent("on"+b,c)}function b(){var a,b=["moz","webkit","o","ms"];for(a=0;a<b.length&&!w;a+=1)w=window[b[a]+"RequestAnimationFrame"];w||c(" RequestAnimationFrame not supported")}function c(a){y.log&&"object"==typeof console&&console.log(s+"[Host page"+u+"]"+a)}function d(a){function b(){function a(){h(z),f(),y.resizedCallback(z)}i(a,z,"resetPage")}function d(a){var b=a.id;c(" Removing iFrame: "+b),a.parentNode.removeChild(a),y.closedCallback(b),c(" --")}function e(){var a=x.substr(t).split(":");return{iframe:document.getElementById(a[0]),id:a[0],height:a[1],width:a[2],type:a[3]}}function j(a){var b=Number(y["max"+a]),d=Number(y["min"+a]),e=a.toLowerCase(),f=Number(z[e]);if(d>b)throw new Error("Value for min"+a+" can not be greater than max"+a);c(" Checking "+e+" is in range "+d+"-"+b),d>f&&(f=d,c(" Set "+e+" to min value")),f>b&&(f=b,c(" Set "+e+" to max value")),z[e]=""+f}function k(){var b=a.origin,d=z.iframe.src.split("/").slice(0,3).join("/");if(y.checkOrigin&&(c(" Checking connection is from: "+d),""+b!="null"&&b!==d))throw new Error("Unexpected message received from: "+b+" for "+z.iframe.id+". Message was: "+a.data+". This error can be disabled by adding the checkOrigin: false option.");return!0}function l(){return s===(""+x).substr(0,t)}function m(){var a=z.type in{"true":1,"false":1};return a&&c(" Ignoring init message from meta parent page"),a}function n(){var a=x.substr(x.indexOf(":")+r+6);c(" MessageCallback passed: {iframe: "+z.iframe.id+", message: "+a+"}"),y.messageCallback({iframe:z.iframe,message:a}),c(" --")}function o(){if(null===z.iframe)throw new Error("iFrame ("+z.id+") does not exist on "+u);return!0}function q(){c(" Reposition requested from iFrame"),v={x:z.width,y:z.height},f()}function w(){switch(z.type){case"close":d(z.iframe),y.resizedCallback(z);break;case"message":n();break;case"scrollTo":q();break;case"reset":g(z);break;case"init":b(),y.initCallback(z.iframe);break;default:b()}}var x=a.data,z={};l()&&(c(" Received: "+x),z=e(),j("Height"),j("Width"),!m()&&o()&&k()&&(w(),p=!1))}function e(){null===v&&(v={x:void 0!==window.pageXOffset?window.pageXOffset:document.documentElement.scrollLeft,y:void 0!==window.pageYOffset?window.pageYOffset:document.documentElement.scrollTop},c(" Get position: "+v.x+","+v.y))}function f(){null!==v&&(window.scrollTo(v.x,v.y),c(" Set position: "+v.x+","+v.y),v=null)}function g(a){function b(){h(a),j("reset","reset",a.iframe)}c(" Size reset requested by "+("init"===a.type?"host page":"iFrame")),e(),i(b,a,"init")}function h(a){function b(b){a.iframe.style[b]=a[b]+"px",c(" IFrame ("+a.iframe.id+") "+b+" set to "+a[b]+"px")}y.sizeHeight&&b("height"),y.sizeWidth&&b("width")}function i(a,b,d){d!==b.type&&w?(c(" Requesting animation frame"),w(a)):a()}function j(a,b,d){c("["+a+"] Sending msg to iframe ("+b+")"),d.contentWindow.postMessage(s+b,"*")}function k(){function b(){function a(a){1/0!==y[a]&&0!==y[a]&&(k.style[a]=y[a]+"px",c(" Set "+a+" = "+y[a]+"px"))}a("maxHeight"),a("minHeight"),a("maxWidth"),a("minWidth")}function d(a){return""===a&&(k.id=a="iFrameResizer"+o++,c(" Added missing iframe ID: "+a+" ("+k.src+")")),a}function e(){c(" IFrame scrolling "+(y.scrolling?"enabled":"disabled")+" for "+l),k.style.overflow=!1===y.scrolling?"hidden":"auto",k.scrolling=!1===y.scrolling?"no":"yes"}function f(){("number"==typeof y.bodyMargin||"0"===y.bodyMargin)&&(y.bodyMarginV1=y.bodyMargin,y.bodyMargin=""+y.bodyMargin+"px")}function h(){return l+":"+y.bodyMarginV1+":"+y.sizeWidth+":"+y.log+":"+y.interval+":"+y.enablePublicMethods+":"+y.autoResize+":"+y.bodyMargin+":"+y.heightCalculationMethod+":"+y.bodyBackground+":"+y.bodyPadding+":"+y.tolerance}function i(b){a(k,"load",function(){var a=p;j("iFrame.onload",b,k),!a&&y.heightCalculationMethod in x&&g({iframe:k,height:0,width:0,type:"init"})}),j("init",b,k)}var k=this,l=d(k.id);e(),b(),f(),i(h())}function l(a){if("object"!=typeof a)throw new TypeError("Options is not an object.")}function m(){function a(a){if("IFRAME"!==a.tagName.toUpperCase())throw new TypeError("Expected <IFRAME> tag, found <"+a.tagName+">.");k.call(a)}function b(a){a=a||{},l(a);for(var b in z)z.hasOwnProperty(b)&&(y[b]=a.hasOwnProperty(b)?a[b]:z[b])}return function(c,d){b(c),Array.prototype.forEach.call(document.querySelectorAll(d||"iframe"),a)}}function n(a){a.fn.iFrameResize=function(b){return b=b||{},l(b),y=a.extend({},z,b),this.filter("iframe").each(k).end()}}var o=0,p=!0,q="message",r=q.length,s="[iFrameSizer]",t=s.length,u="",v=null,w=window.requestAnimationFrame,x={max:1,scroll:1,bodyScroll:1,documentElementScroll:1},y={},z={autoResize:!0,bodyBackground:null,bodyMargin:null,bodyMarginV1:8,bodyPadding:null,checkOrigin:!0,enablePublicMethods:!1,heightCalculationMethod:"offset",interval:32,log:!1,maxHeight:1/0,maxWidth:1/0,minHeight:0,minWidth:0,scrolling:!1,sizeHeight:!0,sizeWidth:!1,tolerance:0,closedCallback:function(){},initCallback:function(){},messageCallback:function(){},resizedCallback:function(){}};b(),a(window,"message",d),"jQuery"in window&&n(jQuery),"function"==typeof define&&define.amd?define(function(){return m()}):window.iFrameResize=m()}();
|
9 |
+
//# sourceMappingURL=../src/iframeResizer.map
|
10 |
+
|
library/otgs/installer/res/js/installer_theme_install.js
CHANGED
@@ -1,97 +1,97 @@
|
|
1 |
-
jQuery( document ).ready( function( $ ) {
|
2 |
-
|
3 |
-
/** Append OTGS Theme tab */
|
4 |
-
var js_array= installer_theme_install_localize.js_array_installer;
|
5 |
-
|
6 |
-
if (!($.isEmptyObject(js_array))) {
|
7 |
-
//Unempty
|
8 |
-
for(var key in js_array) {
|
9 |
-
//Dont append if we are on commercial plugins tab page and if there are no themes
|
10 |
-
if ((!(js_array[key]['is_commercial_plugin_tab'])) && (!(installer_theme_install_localize.no_associated_themes))) {
|
11 |
-
$('div.wp-filter ul.filter-links').append('<li><a data-sort="'+key+'" href="#">'+ js_array[key]['the_hyperlink_text'] +'</a></li>');
|
12 |
-
}
|
13 |
-
}
|
14 |
-
}
|
15 |
-
|
16 |
-
/** Page load event tab selected identifier */
|
17 |
-
var loaded_browsing_tab=installer_theme_extended_object.getParameterByName('browse');
|
18 |
-
if (loaded_browsing_tab.length > 0) {
|
19 |
-
|
20 |
-
var frontend_tab_selected_tab = loaded_browsing_tab;
|
21 |
-
|
22 |
-
} else if (0 == loaded_browsing_tab.length){
|
23 |
-
|
24 |
-
//WordPress defaults to 'Featured' when theme install is loaded without the browse parameter
|
25 |
-
var frontend_tab_selected_tab = 'featured';
|
26 |
-
}
|
27 |
-
|
28 |
-
/** Prepare data on page load event for AJAX */
|
29 |
-
var data = {
|
30 |
-
action: 'installer_theme_frontend_selected_tab',
|
31 |
-
installer_theme_frontend_selected_tab_nonce: installer_theme_install_localize.installer_theme_frontend_selected_tab_nonce,
|
32 |
-
frontend_tab_selected :frontend_tab_selected_tab
|
33 |
-
};
|
34 |
-
|
35 |
-
//Call AJAX
|
36 |
-
installer_theme_extended_object.doAJAX(data,frontend_tab_selected_tab,js_array);
|
37 |
-
|
38 |
-
/** When user clicks on any tab */
|
39 |
-
$(document).on('click','.filter-links li > a',function () {
|
40 |
-
|
41 |
-
//Get data_sort
|
42 |
-
var data_sort =$(this).attr('data-sort');
|
43 |
-
|
44 |
-
if (data_sort) {
|
45 |
-
//data_sort is set, prepare data
|
46 |
-
var data = {
|
47 |
-
action: 'installer_theme_frontend_selected_tab',
|
48 |
-
installer_theme_frontend_selected_tab_nonce: installer_theme_install_localize.installer_theme_frontend_selected_tab_nonce,
|
49 |
-
frontend_tab_selected : data_sort
|
50 |
-
};
|
51 |
-
|
52 |
-
//Call AJAX
|
53 |
-
installer_theme_extended_object.doAJAX(data,data_sort,js_array);
|
54 |
-
|
55 |
-
}
|
56 |
-
});
|
57 |
-
|
58 |
-
var fullhash = window.location.hash;
|
59 |
-
if (fullhash.length > 0) {
|
60 |
-
var product_selector=fullhash+' '+'.enter_site_key_js';
|
61 |
-
if ($(product_selector).length ) {
|
62 |
-
$(product_selector).click();
|
63 |
-
}
|
64 |
-
}
|
65 |
-
});
|
66 |
-
|
67 |
-
//Installer theme extended JS object for methods
|
68 |
-
var installer_theme_extended_object = {
|
69 |
-
|
70 |
-
getParameterByName: function(name) {
|
71 |
-
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
72 |
-
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
73 |
-
results = regex.exec(location.search);
|
74 |
-
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
75 |
-
},
|
76 |
-
|
77 |
-
doAJAX: function(data,data_sort,js_array) {
|
78 |
-
|
79 |
-
//We only want to post to AJAX if its an OTGS tab
|
80 |
-
jQuery.post(installer_theme_install_localize.ajaxurl, data, function(response) {
|
81 |
-
//AJAX response
|
82 |
-
var myObject = jQuery.parseJSON(response);
|
83 |
-
if (typeof myObject != "undefined") {
|
84 |
-
if(myObject.hasOwnProperty("output")){
|
85 |
-
var tab_selected= myObject.output;
|
86 |
-
if (data_sort in js_array) {
|
87 |
-
if (!(installer_theme_install_localize.js_array_installer[tab_selected]['registration_status'])) {
|
88 |
-
//Not registered, no theme response
|
89 |
-
var unregistered_message= myObject.unregistered_messages;
|
90 |
-
jQuery('.no-themes').html(unregistered_message);
|
91 |
-
}
|
92 |
-
}
|
93 |
-
}
|
94 |
-
}
|
95 |
-
});
|
96 |
-
}
|
97 |
};
|
1 |
+
jQuery( document ).ready( function( $ ) {
|
2 |
+
|
3 |
+
/** Append OTGS Theme tab */
|
4 |
+
var js_array= installer_theme_install_localize.js_array_installer;
|
5 |
+
|
6 |
+
if (!($.isEmptyObject(js_array))) {
|
7 |
+
//Unempty
|
8 |
+
for(var key in js_array) {
|
9 |
+
//Dont append if we are on commercial plugins tab page and if there are no themes
|
10 |
+
if ((!(js_array[key]['is_commercial_plugin_tab'])) && (!(installer_theme_install_localize.no_associated_themes))) {
|
11 |
+
$('div.wp-filter ul.filter-links').append('<li><a data-sort="'+key+'" href="#">'+ js_array[key]['the_hyperlink_text'] +'</a></li>');
|
12 |
+
}
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
/** Page load event tab selected identifier */
|
17 |
+
var loaded_browsing_tab=installer_theme_extended_object.getParameterByName('browse');
|
18 |
+
if (loaded_browsing_tab.length > 0) {
|
19 |
+
|
20 |
+
var frontend_tab_selected_tab = loaded_browsing_tab;
|
21 |
+
|
22 |
+
} else if (0 == loaded_browsing_tab.length){
|
23 |
+
|
24 |
+
//WordPress defaults to 'Featured' when theme install is loaded without the browse parameter
|
25 |
+
var frontend_tab_selected_tab = 'featured';
|
26 |
+
}
|
27 |
+
|
28 |
+
/** Prepare data on page load event for AJAX */
|
29 |
+
var data = {
|
30 |
+
action: 'installer_theme_frontend_selected_tab',
|
31 |
+
installer_theme_frontend_selected_tab_nonce: installer_theme_install_localize.installer_theme_frontend_selected_tab_nonce,
|
32 |
+
frontend_tab_selected :frontend_tab_selected_tab
|
33 |
+
};
|
34 |
+
|
35 |
+
//Call AJAX
|
36 |
+
installer_theme_extended_object.doAJAX(data,frontend_tab_selected_tab,js_array);
|
37 |
+
|
38 |
+
/** When user clicks on any tab */
|
39 |
+
$(document).on('click','.filter-links li > a',function () {
|
40 |
+
|
41 |
+
//Get data_sort
|
42 |
+
var data_sort =$(this).attr('data-sort');
|
43 |
+
|
44 |
+
if (data_sort) {
|
45 |
+
//data_sort is set, prepare data
|
46 |
+
var data = {
|
47 |
+
action: 'installer_theme_frontend_selected_tab',
|
48 |
+
installer_theme_frontend_selected_tab_nonce: installer_theme_install_localize.installer_theme_frontend_selected_tab_nonce,
|
49 |
+
frontend_tab_selected : data_sort
|
50 |
+
};
|
51 |
+
|
52 |
+
//Call AJAX
|
53 |
+
installer_theme_extended_object.doAJAX(data,data_sort,js_array);
|
54 |
+
|
55 |
+
}
|
56 |
+
});
|
57 |
+
|
58 |
+
var fullhash = window.location.hash;
|
59 |
+
if (fullhash.length > 0) {
|
60 |
+
var product_selector=fullhash+' '+'.enter_site_key_js';
|
61 |
+
if ($(product_selector).length ) {
|
62 |
+
$(product_selector).click();
|
63 |
+
}
|
64 |
+
}
|
65 |
+
});
|
66 |
+
|
67 |
+
//Installer theme extended JS object for methods
|
68 |
+
var installer_theme_extended_object = {
|
69 |
+
|
70 |
+
getParameterByName: function(name) {
|
71 |
+
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
72 |
+
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
73 |
+
results = regex.exec(location.search);
|
74 |
+
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
75 |
+
},
|
76 |
+
|
77 |
+
doAJAX: function(data,data_sort,js_array) {
|
78 |
+
|
79 |
+
//We only want to post to AJAX if its an OTGS tab
|
80 |
+
jQuery.post(installer_theme_install_localize.ajaxurl, data, function(response) {
|
81 |
+
//AJAX response
|
82 |
+
var myObject = jQuery.parseJSON(response);
|
83 |
+
if (typeof myObject != "undefined") {
|
84 |
+
if(myObject.hasOwnProperty("output")){
|
85 |
+
var tab_selected= myObject.output;
|
86 |
+
if (data_sort in js_array) {
|
87 |
+
if (!(installer_theme_install_localize.js_array_installer[tab_selected]['registration_status'])) {
|
88 |
+
//Not registered, no theme response
|
89 |
+
var unregistered_message= myObject.unregistered_messages;
|
90 |
+
jQuery('.no-themes').html(unregistered_message);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
});
|
96 |
+
}
|
97 |
};
|
library/otgs/installer/templates/downloads-list-compact.php
CHANGED
@@ -1,80 +1,80 @@
|
|
1 |
-
|
2 |
-
<form method="post" class="otgsi_downloads_form">
|
3 |
-
|
4 |
-
<table class="installer-plugins-list-compact">
|
5 |
-
<thead>
|
6 |
-
<tr>
|
7 |
-
<th> </th>
|
8 |
-
<th><?php _e('Plugin', 'installer') ?></th>
|
9 |
-
<th><img src="<?php echo $this->plugin_url() ?>/res/img/globe.png" alt="<?php esc_attr_e('Available', 'installer') ?>" width="16" height="16"></th>
|
10 |
-
<th><img src="<?php echo $this->plugin_url() ?>/res/img/computer.png" alt="<?php esc_attr_e('Installed', 'installer') ?>" width="16" height="16"></th>
|
11 |
-
<th><img src="<?php echo $this->plugin_url() ?>/res/img/dn2.gif" alt="<?php esc_attr_e('Downloading', 'installer') ?>" width="16" height="16"></th>
|
12 |
-
<th><img src="<?php echo $this->plugin_url() ?>/res/img/on.png" alt="<?php esc_attr_e('Activate', 'installer') ?>" width="16" height="16"></th>
|
13 |
-
</tr>
|
14 |
-
</thead>
|
15 |
-
<tbody>
|
16 |
-
<?php foreach($product['downloads'] as $download): ?>
|
17 |
-
<?php if(empty($tr_oddeven) || $tr_oddeven == 'even') $tr_oddeven = 'odd'; else $tr_oddeven = 'even'; ?>
|
18 |
-
<tr class="<?php echo $tr_oddeven ?>">
|
19 |
-
<td>
|
20 |
-
<label>
|
21 |
-
<?php
|
22 |
-
$url = $this->append_site_key_to_download_url($download['url'], $site_key, $repository_id );
|
23 |
-
|
24 |
-
$download_data = array(
|
25 |
-
'url' => $url,
|
26 |
-
'slug' => $download['slug'],
|
27 |
-
'nonce' => wp_create_nonce('install_plugin_' . $url),
|
28 |
-
'repository_id' => $repository_id
|
29 |
-
);
|
30 |
-
|
31 |
-
$disabled = $expired ||
|
32 |
-
(
|
33 |
-
$this->plugin_is_installed($download['name'], $download['slug'], $download['version']) &&
|
34 |
-
!$this->plugin_is_embedded_version($download['name'], $download['slug'])
|
35 |
-
) || WP_Installer()->dependencies->cant_download( $repository_id );
|
36 |
-
|
37 |
-
?>
|
38 |
-
<input type="checkbox" name="downloads[]" value="<?php echo base64_encode(json_encode($download_data)); ?>" <?php
|
39 |
-
if($disabled): ?>disabled="disabled"<?php endif; ?> />
|
40 |
-
|
41 |
-
</label>
|
42 |
-
</td>
|
43 |
-
<td class="installer_plugin_name"><?php echo $download['name'] ?></td>
|
44 |
-
<td><?php echo $download['version'] ?></td>
|
45 |
-
<td class="installer_version_installed">
|
46 |
-
<?php if($v = $this->plugin_is_installed($download['name'], $download['slug'])):
|
47 |
-
$class = version_compare($v, $download['version'], '>=') ? 'installer-green-text' : 'installer-red-text'; ?>
|
48 |
-
<span class="<?php echo $class ?>"><?php echo $v; ?></span>
|
49 |
-
<?php endif; ?>
|
50 |
-
</td>
|
51 |
-
<td class="twelve">
|
52 |
-
<div class="installer-status-downloading"><?php _e('downloading...', 'installer') ?></div>
|
53 |
-
<div class="installer-status-downloaded" data-fail="<?php _e('failed!', 'installer') ?>"><?php _e('downloaded', 'installer') ?></div>
|
54 |
-
</td>
|
55 |
-
<td class="twelve">
|
56 |
-
<div class="installer-status-activating"><?php _e('activating', 'installer') ?></div>
|
57 |
-
<div class="installer-status-activated"><?php _e('activated', 'installer') ?></div>
|
58 |
-
</td>
|
59 |
-
</tr>
|
60 |
-
<?php endforeach; ?>
|
61 |
-
</tbody>
|
62 |
-
</table>
|
63 |
-
|
64 |
-
<?php if( !WP_Installer()->dependencies->is_uploading_allowed() ): ?>
|
65 |
-
<p class="installer-error-box"><?php printf(__('Downloading is not possible because WordPress cannot write into the plugins folder. %sHow to fix%s.', 'installer'),
|
66 |
-
'<a href="http://codex.wordpress.org/Changing_File_Permissions">', '</a>') ?></p>
|
67 |
-
<?php elseif( WP_Installer()->dependencies->is_win_paths_exception($repository_id) ): ?>
|
68 |
-
<p><?php echo WP_Installer()->dependencies->win_paths_exception_message() ?></p>
|
69 |
-
<?php endif;?>
|
70 |
-
|
71 |
-
<br />
|
72 |
-
<input type="submit" class="button-secondary" value="<?php esc_attr_e('Download', 'installer') ?>" disabled="disabled" />
|
73 |
-
|
74 |
-
<label><input name="activate" type="checkbox" value="1" disabled="disabled" /> <?php _e('Activate after download', 'installer') ?></label>
|
75 |
-
|
76 |
-
<div class="installer-download-progress-status"></div>
|
77 |
-
<div class="installer-status-success"><?php _e('Operation complete!', 'installer') ?></div>
|
78 |
-
|
79 |
-
<span class="installer-revalidate-message hidden"><?php _e("Download failed!\n\nClick OK to revalidate your subscription or CANCEL to try again.", 'installer') ?></span>
|
80 |
-
</form>
|
1 |
+
|
2 |
+
<form method="post" class="otgsi_downloads_form">
|
3 |
+
|
4 |
+
<table class="installer-plugins-list-compact">
|
5 |
+
<thead>
|
6 |
+
<tr>
|
7 |
+
<th> </th>
|
8 |
+
<th><?php _e('Plugin', 'installer') ?></th>
|
9 |
+
<th><img src="<?php echo $this->plugin_url() ?>/res/img/globe.png" alt="<?php esc_attr_e('Available', 'installer') ?>" width="16" height="16"></th>
|
10 |
+
<th><img src="<?php echo $this->plugin_url() ?>/res/img/computer.png" alt="<?php esc_attr_e('Installed', 'installer') ?>" width="16" height="16"></th>
|
11 |
+
<th><img src="<?php echo $this->plugin_url() ?>/res/img/dn2.gif" alt="<?php esc_attr_e('Downloading', 'installer') ?>" width="16" height="16"></th>
|
12 |
+
<th><img src="<?php echo $this->plugin_url() ?>/res/img/on.png" alt="<?php esc_attr_e('Activate', 'installer') ?>" width="16" height="16"></th>
|
13 |
+
</tr>
|
14 |
+
</thead>
|
15 |
+
<tbody>
|
16 |
+
<?php foreach($product['downloads'] as $download): ?>
|
17 |
+
<?php if(empty($tr_oddeven) || $tr_oddeven == 'even') $tr_oddeven = 'odd'; else $tr_oddeven = 'even'; ?>
|
18 |
+
<tr class="<?php echo $tr_oddeven ?>">
|
19 |
+
<td>
|
20 |
+
<label>
|
21 |
+
<?php
|
22 |
+
$url = $this->append_site_key_to_download_url($download['url'], $site_key, $repository_id );
|
23 |
+
|
24 |
+
$download_data = array(
|
25 |
+
'url' => $url,
|
26 |
+
'slug' => $download['slug'],
|
27 |
+
'nonce' => wp_create_nonce('install_plugin_' . $url),
|
28 |
+
'repository_id' => $repository_id
|
29 |
+
);
|
30 |
+
|
31 |
+
$disabled = $expired ||
|
32 |
+
(
|
33 |
+
$this->plugin_is_installed($download['name'], $download['slug'], $download['version']) &&
|
34 |
+
!$this->plugin_is_embedded_version($download['name'], $download['slug'])
|
35 |
+
) || WP_Installer()->dependencies->cant_download( $repository_id );
|
36 |
+
|
37 |
+
?>
|
38 |
+
<input type="checkbox" name="downloads[]" value="<?php echo base64_encode(json_encode($download_data)); ?>" <?php
|
39 |
+
if($disabled): ?>disabled="disabled"<?php endif; ?> />
|
40 |
+
|
41 |
+
</label>
|
42 |
+
</td>
|
43 |
+
<td class="installer_plugin_name"><?php echo $download['name'] ?></td>
|
44 |
+
<td><?php echo $download['version'] ?></td>
|
45 |
+
<td class="installer_version_installed">
|
46 |
+
<?php if($v = $this->plugin_is_installed($download['name'], $download['slug'])):
|
47 |
+
$class = version_compare($v, $download['version'], '>=') ? 'installer-green-text' : 'installer-red-text'; ?>
|
48 |
+
<span class="<?php echo $class ?>"><?php echo $v; ?></span>
|
49 |
+
<?php endif; ?>
|
50 |
+
</td>
|
51 |
+
<td class="twelve">
|
52 |
+
<div class="installer-status-downloading"><?php _e('downloading...', 'installer') ?></div>
|
53 |
+
<div class="installer-status-downloaded" data-fail="<?php _e('failed!', 'installer') ?>"><?php _e('downloaded', 'installer') ?></div>
|
54 |
+
</td>
|
55 |
+
<td class="twelve">
|
56 |
+
<div class="installer-status-activating"><?php _e('activating', 'installer') ?></div>
|
57 |
+
<div class="installer-status-activated"><?php _e('activated', 'installer') ?></div>
|
58 |
+
</td>
|
59 |
+
</tr>
|
60 |
+
<?php endforeach; ?>
|
61 |
+
</tbody>
|
62 |
+
</table>
|
63 |
+
|
64 |
+
<?php if( !WP_Installer()->dependencies->is_uploading_allowed() ): ?>
|
65 |
+
<p class="installer-error-box"><?php printf(__('Downloading is not possible because WordPress cannot write into the plugins folder. %sHow to fix%s.', 'installer'),
|
66 |
+
'<a href="http://codex.wordpress.org/Changing_File_Permissions">', '</a>') ?></p>
|
67 |
+
<?php elseif( WP_Installer()->dependencies->is_win_paths_exception($repository_id) ): ?>
|
68 |
+
<p><?php echo WP_Installer()->dependencies->win_paths_exception_message() ?></p>
|
69 |
+
<?php endif;?>
|
70 |
+
|
71 |
+
<br />
|
72 |
+
<input type="submit" class="button-secondary" value="<?php esc_attr_e('Download', 'installer') ?>" disabled="disabled" />
|
73 |
+
|
74 |
+
<label><input name="activate" type="checkbox" value="1" disabled="disabled" /> <?php _e('Activate after download', 'installer') ?></label>
|
75 |
+
|
76 |
+
<div class="installer-download-progress-status"></div>
|
77 |
+
<div class="installer-status-success"><?php _e('Operation complete!', 'installer') ?></div>
|
78 |
+
|
79 |
+
<span class="installer-revalidate-message hidden"><?php _e("Download failed!\n\nClick OK to revalidate your subscription or CANCEL to try again.", 'installer') ?></span>
|
80 |
+
</form>
|
library/otgs/installer/templates/downloads-list.php
CHANGED
@@ -1,85 +1,85 @@
|
|
1 |
-
<br clear="all" /><br />
|
2 |
-
<strong><?php _e('Downloads:', 'installer') ?></strong>
|
3 |
-
|
4 |
-
<form method="post" class="otgsi_downloads_form">
|
5 |
-
|
6 |
-
<table class="widefat">
|
7 |
-
<thead>
|
8 |
-
<tr>
|
9 |
-
<th> </th>
|
10 |
-
<th><?php _e('Plugin', 'installer') ?></th>
|
11 |
-
<th><?php _e('Current version', 'installer') ?></th>
|
12 |
-
<th><?php _e('Released', 'installer') ?></th>
|
13 |
-
<th><?php _e('Installed version', 'installer') ?></th>
|
14 |
-
<th> </th>
|
15 |
-
<th> </th>
|
16 |
-
<th> </th>
|
17 |
-
</tr>
|
18 |
-
</thead>
|
19 |
-
<tbody>
|
20 |
-
<?php
|
21 |
-
foreach($package['downloads'] as $download): ?>
|
22 |
-
<tr>
|
23 |
-
<td>
|
24 |
-
<label>
|
25 |
-
<?php
|
26 |
-
$url = $this->append_site_key_to_download_url($download['url'], $site_key, $repository_id);
|
27 |
-
|
28 |
-
$download_data = array(
|
29 |
-
'url' => $url,
|
30 |
-
'slug' => $download['slug'],
|
31 |
-
'nonce' => wp_create_nonce('install_plugin_' . $url),
|
32 |
-
'repository_id' => $repository_id
|
33 |
-
);
|
34 |
-
?>
|
35 |
-
<input type="checkbox" name="downloads[]" value="<?php echo base64_encode(json_encode($download_data)); ?>" <?php
|
36 |
-
if($this->plugin_is_installed($download['name'], $download['slug'], $download['version']) && !$this->plugin_is_embedded_version($download['name'], $download['slug']) || WP_Installer()->dependencies->cant_download($repository_id) ): ?>disabled="disabled"<?php endif; ?> />
|
37 |
-
|
38 |
-
</label>
|
39 |
-
</td>
|
40 |
-
<td class="installer_plugin_name"><?php echo $download['name'] ?></td>
|
41 |
-
<td><?php echo $download['version'] ?></td>
|
42 |
-
<td><?php echo date_i18n('F j, Y', strtotime($download['date'])) ?></td>
|
43 |
-
<td class="installer_version_installed">
|
44 |
-
<?php if($v = $this->plugin_is_installed($download['name'], $download['slug'])): $class = version_compare($v, $download['version'], '>=') ? 'installer-green-text' : 'installer-red-text'; ?>
|
45 |
-
<span class="<?php echo $class ?>"><?php echo $v; ?></span>
|
46 |
-
<?php if($this->plugin_is_embedded_version($download['name'], $download['slug'])): ?> <?php _e('(embedded)', 'installer'); ?><?php endif; ?>
|
47 |
-
<?php endif; ?>
|
48 |
-
</td>
|
49 |
-
<td>
|
50 |
-
<span class="installer-status-installing"><?php _e('installing...', 'installer') ?></span>
|
51 |
-
<span class="installer-status-updating"><?php _e('updating...', 'installer') ?></span>
|
52 |
-
<span class="installer-status-installed" data-fail="<?php _e('failed!', 'installer') ?>"><?php _e('installed', 'installer') ?></span>
|
53 |
-
<span class="installer-status-updated" data-fail="<?php _e('failed!', 'installer') ?>"><?php _e('updated', 'installer') ?></span>
|
54 |
-
</td>
|
55 |
-
<td>
|
56 |
-
<span class="installer-status-activating"><?php _e('activating', 'installer') ?></span>
|
57 |
-
<span class="installer-status-activated"><?php _e('activated', 'installer') ?></span>
|
58 |
-
</td>
|
59 |
-
<td class="for_spinner_js"><span class="spinner"></span></td>
|
60 |
-
</tr>
|
61 |
-
<?php endforeach; ?>
|
62 |
-
</tbody>
|
63 |
-
</table>
|
64 |
-
|
65 |
-
<br />
|
66 |
-
|
67 |
-
<div class="installer-error-box">
|
68 |
-
<?php if( !WP_Installer()->dependencies->is_uploading_allowed() ): ?>
|
69 |
-
<p><?php printf(__('Downloading is not possible because WordPress cannot write into the plugins folder. %sHow to fix%s.', 'installer'),
|
70 |
-
'<a href="http://codex.wordpress.org/Changing_File_Permissions">', '</a>') ?></p>
|
71 |
-
<?php elseif( WP_Installer()->dependencies->is_win_paths_exception($repository_id) ): ?>
|
72 |
-
<p><?php echo WP_Installer()->dependencies->win_paths_exception_message() ?></p>
|
73 |
-
<?php endif; ?>
|
74 |
-
</div>
|
75 |
-
|
76 |
-
<input type="submit" class="button-secondary" value="<?php esc_attr_e('Download', 'installer') ?>" disabled="disabled" />
|
77 |
-
|
78 |
-
<label><input name="activate" type="checkbox" value="1" disabled="disabled" /> <?php _e('Activate after download', 'installer') ?></label>
|
79 |
-
|
80 |
-
<div class="installer-download-progress-status"></div>
|
81 |
-
|
82 |
-
<div class="installer-status-success"><?php _e('Operation complete!', 'installer') ?></div>
|
83 |
-
|
84 |
-
<span class="installer-revalidate-message hidden"><?php _e("Download failed!\n\nPlease refresh the page and try again.", 'installer') ?></span>
|
85 |
-
</form>
|
1 |
+
<br clear="all" /><br />
|
2 |
+
<strong><?php _e('Downloads:', 'installer') ?></strong>
|
3 |
+
|
4 |
+
<form method="post" class="otgsi_downloads_form">
|
5 |
+
|
6 |
+
<table class="widefat">
|
7 |
+
<thead>
|
8 |
+
<tr>
|
9 |
+
<th> </th>
|
10 |
+
<th><?php _e('Plugin', 'installer') ?></th>
|
11 |
+
<th><?php _e('Current version', 'installer') ?></th>
|
12 |
+
<th><?php _e('Released', 'installer') ?></th>
|
13 |
+
<th><?php _e('Installed version', 'installer') ?></th>
|
14 |
+
<th> </th>
|
15 |
+
<th> </th>
|
16 |
+
<th> </th>
|
17 |
+
</tr>
|
18 |
+
</thead>
|
19 |
+
<tbody>
|
20 |
+
<?php
|
21 |
+
foreach($package['downloads'] as $download): ?>
|
22 |
+
<tr>
|
23 |
+
<td>
|
24 |
+
<label>
|
25 |
+
<?php
|
26 |
+
$url = $this->append_site_key_to_download_url($download['url'], $site_key, $repository_id);
|
27 |
+
|
28 |
+
$download_data = array(
|
29 |
+
'url' => $url,
|
30 |
+
'slug' => $download['slug'],
|
31 |
+
'nonce' => wp_create_nonce('install_plugin_' . $url),
|
32 |
+
'repository_id' => $repository_id
|
33 |
+
);
|
34 |
+
?>
|
35 |
+
<input type="checkbox" name="downloads[]" value="<?php echo base64_encode(json_encode($download_data)); ?>" <?php
|
36 |
+
if($this->plugin_is_installed($download['name'], $download['slug'], $download['version']) && !$this->plugin_is_embedded_version($download['name'], $download['slug']) || WP_Installer()->dependencies->cant_download($repository_id) ): ?>disabled="disabled"<?php endif; ?> />
|
37 |
+
|
38 |
+
</label>
|
39 |
+
</td>
|
40 |
+
<td class="installer_plugin_name"><?php echo $download['name'] ?></td>
|
41 |
+
<td><?php echo $download['version'] ?></td>
|
42 |
+
<td><?php echo date_i18n('F j, Y', strtotime($download['date'])) ?></td>
|
43 |
+
<td class="installer_version_installed">
|
44 |
+
<?php if($v = $this->plugin_is_installed($download['name'], $download['slug'])): $class = version_compare($v, $download['version'], '>=') ? 'installer-green-text' : 'installer-red-text'; ?>
|
45 |
+
<span class="<?php echo $class ?>"><?php echo $v; ?></span>
|
46 |
+
<?php if($this->plugin_is_embedded_version($download['name'], $download['slug'])): ?> <?php _e('(embedded)', 'installer'); ?><?php endif; ?>
|
47 |
+
<?php endif; ?>
|
48 |
+
</td>
|
49 |
+
<td>
|
50 |
+
<span class="installer-status-installing"><?php _e('installing...', 'installer') ?></span>
|
51 |
+
<span class="installer-status-updating"><?php _e('updating...', 'installer') ?></span>
|
52 |
+
<span class="installer-status-installed" data-fail="<?php _e('failed!', 'installer') ?>"><?php _e('installed', 'installer') ?></span>
|
53 |
+
<span class="installer-status-updated" data-fail="<?php _e('failed!', 'installer') ?>"><?php _e('updated', 'installer') ?></span>
|
54 |
+
</td>
|
55 |
+
<td>
|
56 |
+
<span class="installer-status-activating"><?php _e('activating', 'installer') ?></span>
|
57 |
+
<span class="installer-status-activated"><?php _e('activated', 'installer') ?></span>
|
58 |
+
</td>
|
59 |
+
<td class="for_spinner_js"><span class="spinner"></span></td>
|
60 |
+
</tr>
|
61 |
+
<?php endforeach; ?>
|
62 |
+
</tbody>
|
63 |
+
</table>
|
64 |
+
|
65 |
+
<br />
|
66 |
+
|
67 |
+
<div class="installer-error-box">
|
68 |
+
<?php if( !WP_Installer()->dependencies->is_uploading_allowed() ): ?>
|
69 |
+
<p><?php printf(__('Downloading is not possible because WordPress cannot write into the plugins folder. %sHow to fix%s.', 'installer'),
|
70 |
+
'<a href="http://codex.wordpress.org/Changing_File_Permissions">', '</a>') ?></p>
|
71 |
+
<?php elseif( WP_Installer()->dependencies->is_win_paths_exception($repository_id) ): ?>
|
72 |
+
<p><?php echo WP_Installer()->dependencies->win_paths_exception_message() ?></p>
|
73 |
+
<?php endif; ?>
|
74 |
+
</div>
|
75 |
+
|
76 |
+
<input type="submit" class="button-secondary" value="<?php esc_attr_e('Download', 'installer') ?>" disabled="disabled" />
|
77 |
+
|
78 |
+
<label><input name="activate" type="checkbox" value="1" disabled="disabled" /> <?php _e('Activate after download', 'installer') ?></label>
|
79 |
+
|
80 |
+
<div class="installer-download-progress-status"></div>
|
81 |
+
|
82 |
+
<div class="installer-status-success"><?php _e('Operation complete!', 'installer') ?></div>
|
83 |
+
|
84 |
+
<span class="installer-revalidate-message hidden"><?php _e("Download failed!\n\nPlease refresh the page and try again.", 'installer') ?></span>
|
85 |
+
</form>
|
library/otgs/installer/templates/products-compact.php
CHANGED
@@ -1,129 +1,147 @@
|
|
1 |
-
<h3><?php echo $args['box_title'] ?></h3>
|
2 |
-
|
3 |
-
<?php
|
4 |
-
if(empty($args['repository']) || empty($args['package']) || empty($args['product'])){
|
5 |
-
echo __('Incorrect setup', 'installer');
|
6 |
-
return;
|
7 |
-
}
|
8 |
-
|
9 |
-
$product = false;
|
10 |
-
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package_idx => $package){
|
11 |
-
|
12 |
-
//pre 1.3 backwardds compatibility
|
13 |
-
if(!isset($package['id'])){
|
14 |
-
$package['id'] = sanitize_title_with_dashes($package['name']);
|
15 |
-
}
|
16 |
-
|
17 |
-
if($package['id'] == $args['package']){
|
18 |
-
$product = $this->settings['repositories'][$repository_id]['data']['packages'][$package_idx]['products'][$args['product']];
|
19 |
-
break;
|
20 |
-
}
|
21 |
-
}
|
22 |
-
|
23 |
-
|
24 |
-
if(!$product){
|
25 |
-
echo __('Invalid product', 'installer');
|
26 |
-
return;
|
27 |
-
}
|
28 |
-
|
29 |
-
if(isset($this->settings['repositories'][$repository_id])){
|
30 |
-
if(isset($this->settings['repositories'][$repository_id]['subscription']['key'])){
|
31 |
-
$site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
|
32 |
-
}else{
|
33 |
-
$site_key = false;
|
34 |
-
}
|
35 |
-
}else{
|
36 |
-
echo __('Unknown repository', 'installer');
|
37 |
-
return;
|
38 |
-
}
|
39 |
-
|
40 |
-
$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
41 |
-
$expired = false;
|
42 |
-
|
43 |
-
if($subscription_type != $product['subscription_type'] && !$this->have_superior_subscription($subscription_type, $product) && $site_key){
|
44 |
-
$subscription_no_match = sprintf(__(' Your current site key (%s) does not match the selected product (%s).', 'installer'), $site_key, $product['name']);
|
45 |
-
}
|
46 |
-
|
47 |
-
if(!isset($args['product_name'])) $args['product_name'] = $product['name'];
|
48 |
-
|
49 |
-
?>
|
50 |
-
|
51 |
-
<div class="otgs_wp_installer_table otgs_wp_installer_table_compact">
|
52 |
-
|
53 |
-
<p><?php echo $args['box_description'] ?></p>
|
54 |
-
|
55 |
-
|
56 |
-
<?php if(!$this->repository_has_subscription($repository_id) || !empty($subscription_no_match)): ?>
|
57 |
-
|
58 |
-
<?php if(!empty($subscription_no_match)): ?>
|
59 |
-
<div class="installer-warn-box">
|
60 |
-
<?php echo $subscription_no_match; ?>
|
61 |
-
</div>
|
62 |
-
<br />
|
63 |
-
<?php endif; ?>
|
64 |
-
|
65 |
-
<a class="button-primary" href="<?php echo $this->append_parameters_to_buy_url($product['url'], $repository_id, $args) ?>"><?php printf(__('Buy %s', 'installer'), $args['product_name']) ?></a>
|
66 |
-
|
67 |
-
<div>
|
68 |
-
<br />
|
69 |
-
<?php printf(__('Already bought %s?', 'installer'), $args['product_name']) ?>
|
70 |
-
<a class="enter_site_key_js
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
</
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
<?php
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
<?php
|
116 |
-
if(
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
<?php
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
<?php
|
128 |
-
|
129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<h3><?php echo $args['box_title'] ?></h3>
|
2 |
+
|
3 |
+
<?php
|
4 |
+
if(empty($args['repository']) || empty($args['package']) || empty($args['product'])){
|
5 |
+
echo __('Incorrect setup', 'installer');
|
6 |
+
return;
|
7 |
+
}
|
8 |
+
|
9 |
+
$product = false;
|
10 |
+
foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package_idx => $package){
|
11 |
+
|
12 |
+
//pre 1.3 backwardds compatibility
|
13 |
+
if(!isset($package['id'])){
|
14 |
+
$package['id'] = sanitize_title_with_dashes($package['name']);
|
15 |
+
}
|
16 |
+
|
17 |
+
if($package['id'] == $args['package']){
|
18 |
+
$product = $this->settings['repositories'][$repository_id]['data']['packages'][$package_idx]['products'][$args['product']];
|
19 |
+
break;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
|
24 |
+
if(!$product){
|
25 |
+
echo __('Invalid product', 'installer');
|
26 |
+
return;
|
27 |
+
}
|
28 |
+
|
29 |
+
if(isset($this->settings['repositories'][$repository_id])){
|
30 |
+
if(isset($this->settings['repositories'][$repository_id]['subscription']['key'])){
|
31 |
+
$site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
|
32 |
+
}else{
|
33 |
+
$site_key = false;
|
34 |
+
}
|
35 |
+
}else{
|
36 |
+
echo __('Unknown repository', 'installer');
|
37 |
+
return;
|
38 |
+
}
|
39 |
+
|
40 |
+
$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
41 |
+
$expired = false;
|
42 |
+
|
43 |
+
if($subscription_type != $product['subscription_type'] && !$this->have_superior_subscription($subscription_type, $product) && $site_key){
|
44 |
+
$subscription_no_match = sprintf(__(' Your current site key (%s) does not match the selected product (%s).', 'installer'), $site_key, $product['name']);
|
45 |
+
}
|
46 |
+
|
47 |
+
if(!isset($args['product_name'])) $args['product_name'] = $product['name'];
|
48 |
+
|
49 |
+
?>
|
50 |
+
|
51 |
+
<div class="otgs_wp_installer_table otgs_wp_installer_table_compact">
|
52 |
+
|
53 |
+
<p><?php echo $args['box_description'] ?></p>
|
54 |
+
|
55 |
+
|
56 |
+
<?php if(!$this->repository_has_subscription($repository_id) || !empty($subscription_no_match)): ?>
|
57 |
+
|
58 |
+
<?php if(!empty($subscription_no_match)): ?>
|
59 |
+
<div class="installer-warn-box">
|
60 |
+
<?php echo $subscription_no_match; ?>
|
61 |
+
</div>
|
62 |
+
<br />
|
63 |
+
<?php endif; ?>
|
64 |
+
|
65 |
+
<a class="button-primary" href="<?php echo $this->append_parameters_to_buy_url($product['url'], $repository_id, $args) ?>"><?php printf(__('Buy %s', 'installer'), $args['product_name']) ?></a>
|
66 |
+
|
67 |
+
<div>
|
68 |
+
<br />
|
69 |
+
<?php printf(__('Already bought %s?', 'installer'), $args['product_name']) ?>
|
70 |
+
<a class="enter_site_key_js<?php if( WP_Installer::get_repository_hardcoded_site_key( $repository_id ) ): ?> disabled<?php endif ?>" href="#"
|
71 |
+
<?php if( WP_Installer::get_repository_hardcoded_site_key( $repository_id ) ): ?>
|
72 |
+
style="cursor: help"
|
73 |
+
disabled="disabled"
|
74 |
+
title="<?php printf( esc_attr__("Site-key was set by %s, most likely in wp-config.php. Please remove the constant before attempting to register.", 'installer'), 'OTGS_INSTALLER_SITE_KEY_' . strtoupper($repository_id) ) ?>"
|
75 |
+
<?php endif; ?>
|
76 |
+
>
|
77 |
+
<?php _e('Enter site key', 'installer') ?>
|
78 |
+
</a>
|
79 |
+
|
80 |
+
<form class="otgsi_site_key_form" method="post">
|
81 |
+
<input type="hidden" name="action" value="save_site_key" />
|
82 |
+
<input type="hidden" name="nonce" value="<?php echo wp_create_nonce('save_site_key_' . $repository_id) ?>" />
|
83 |
+
<input type="hidden" name="repository_id" value="<?php echo $repository_id ?>">
|
84 |
+
<input type="text" size="10" name="site_key_<?php echo $repository_id ?>" />
|
85 |
+
<input class="button-secondary" type="submit" value="<?php esc_attr_e('Add', 'installer') ?>" />
|
86 |
+
</form>
|
87 |
+
<div class="installer-error-box hidden" style="margin-top:10px;"></div>
|
88 |
+
</div>
|
89 |
+
|
90 |
+
<?php else: ?>
|
91 |
+
|
92 |
+
<?php if($this->repository_has_expired_subscription($repository_id)): $expired = true; ?>
|
93 |
+
|
94 |
+
<div><p class="installer-warn-box"><?php _e('Subscription is expired.', 'installer') ?></p></div>
|
95 |
+
|
96 |
+
<?php else: ?>
|
97 |
+
|
98 |
+
<?php if($this->show_subscription_renew_warning($repository_id, $subscription_type)): ?>
|
99 |
+
|
100 |
+
<ul class="installer-products-list">
|
101 |
+
<?php foreach($product['renewals'] as $renewal): ?>
|
102 |
+
<li>
|
103 |
+
<a href="<?php echo $this->append_parameters_to_buy_url($renewal['url'], $repository_id, $args) ?>"><?php printf(__('Renew %s', 'installer'), $args['product_name']) ?></a>
|
104 |
+
</li>
|
105 |
+
<?php endforeach; ?>
|
106 |
+
</ul>
|
107 |
+
|
108 |
+
<?php endif; ?>
|
109 |
+
|
110 |
+
<?php endif; ?>
|
111 |
+
|
112 |
+
<center>
|
113 |
+
<a class="remove_site_key_js" href="#" data-repository=<?php echo $repository_id ?>
|
114 |
+
data-confirmation="<?php esc_attr_e('Are you sure you want to remove this site key?', 'installer') ?>"
|
115 |
+
data-nonce="<?php echo wp_create_nonce('remove_site_key_' . $repository_id) ?>"
|
116 |
+
<?php if( WP_Installer::get_repository_hardcoded_site_key( $repository_id ) ): ?>
|
117 |
+
style="cursor: help;color:#999999"
|
118 |
+
disabled="disabled"
|
119 |
+
title="<?php printf( esc_attr__("Site-key was set by %s, most likely in wp-config.php. Please remove the constant before attempting to unregister.", 'installer'), 'OTGS_INSTALLER_SITE_KEY_' . strtoupper($repository_id) ) ?>"
|
120 |
+
<?php endif; ?>
|
121 |
+
>
|
122 |
+
<?php printf(__("Remove current site key (%s)", 'installer'), $site_key) ?>
|
123 |
+
</a>
|
124 |
+
</center>
|
125 |
+
<br />
|
126 |
+
|
127 |
+
<?php include $this->plugin_path() . '/templates/downloads-list-compact.php'; ?>
|
128 |
+
|
129 |
+
|
130 |
+
|
131 |
+
<?php endif; ?>
|
132 |
+
|
133 |
+
<?php
|
134 |
+
if( isset( $args[ 'name' ] ) ):
|
135 |
+
$support_link = $this->get_support_tag_by_name($args['name'], $args['repository']); ?>
|
136 |
+
|
137 |
+
<?php if($support_link): ?>
|
138 |
+
<p><a href="<?php echo $support_link ?>" target="_blank"><?php printf(__('%s support on wpml.org', 'installer'), $args['name'] ) ?></a></p>
|
139 |
+
|
140 |
+
<?php endif; ?>
|
141 |
+
<?php
|
142 |
+
// compatibility for installer 1.1
|
143 |
+
elseif( isset( $args[ 'support_link' ] ) ): ?>
|
144 |
+
<p><?php echo $args[ 'support_link' ]; ?></p>
|
145 |
+
<?php endif; ?>
|
146 |
+
|
147 |
+
</div>
|
library/otgs/installer/templates/repository-listing.php
CHANGED
@@ -1,179 +1,196 @@
|
|
1 |
-
<?php if((!$this->repository_has_subscription($repository_id) && $match = $this->get_matching_cp($repository)) && $match['exp']): ?>
|
2 |
-
<p class="alignright installer_highlight"><strong><?php printf('Price offers available until %s', date_i18n(get_option( 'date_format' ), $match['exp'])) ?></strong></p>
|
3 |
-
<?php endif; ?>
|
4 |
-
|
5 |
-
<h3 id="repository-<?php echo $repository_id ?>"><?php echo $repository['data']['name'] ?></h3>
|
6 |
-
<?php
|
7 |
-
$generic_product_name = $this->settings['repositories'][$repository_id]['data']['product-name'];
|
8 |
-
?>
|
9 |
-
<table class="widefat otgs_wp_installer_table" id="installer_repo_<?php echo $repository_id ?>">
|
10 |
-
|
11 |
-
<tr>
|
12 |
-
<td> </td>
|
13 |
-
<td class="otgsi_register_product_wrap" align="center" valign="top">
|
14 |
-
<?php // IF NO SUBSCRIPTION ?>
|
15 |
-
<?php if(!$this->repository_has_subscription($repository_id)): ?>
|
16 |
-
|
17 |
-
<div style="text-align: right;">
|
18 |
-
<span><?php _e('Already bought?', 'installer'); ?> </span>
|
19 |
-
<a class="enter_site_key_js button-primary
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
<
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
$
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
<?php
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
<?php
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if((!$this->repository_has_subscription($repository_id) && $match = $this->get_matching_cp($repository)) && $match['exp']): ?>
|
2 |
+
<p class="alignright installer_highlight"><strong><?php printf('Price offers available until %s', date_i18n(get_option( 'date_format' ), $match['exp'])) ?></strong></p>
|
3 |
+
<?php endif; ?>
|
4 |
+
|
5 |
+
<h3 id="repository-<?php echo $repository_id ?>"><?php echo $repository['data']['name'] ?></h3>
|
6 |
+
<?php
|
7 |
+
$generic_product_name = $this->settings['repositories'][$repository_id]['data']['product-name'];
|
8 |
+
?>
|
9 |
+
<table class="widefat otgs_wp_installer_table" id="installer_repo_<?php echo $repository_id ?>">
|
10 |
+
|
11 |
+
<tr>
|
12 |
+
<td> </td>
|
13 |
+
<td class="otgsi_register_product_wrap" align="center" valign="top">
|
14 |
+
<?php // IF NO SUBSCRIPTION ?>
|
15 |
+
<?php if(!$this->repository_has_subscription($repository_id)): ?>
|
16 |
+
|
17 |
+
<div style="text-align: right;">
|
18 |
+
<span><?php _e('Already bought?', 'installer'); ?> </span>
|
19 |
+
<a class="enter_site_key_js button-primary<?php if( WP_Installer::get_repository_hardcoded_site_key( $repository_id ) ): ?> disabled<?php endif ?>" href="#"
|
20 |
+
<?php if( WP_Installer::get_repository_hardcoded_site_key( $repository_id ) ): ?>
|
21 |
+
style="cursor: help"
|
22 |
+
disabled="disabled"
|
23 |
+
title="<?php printf( esc_attr__("Site-key was set by %s, most likely in wp-config.php. Please remove the constant before attempting to register.", 'installer'), 'OTGS_INSTALLER_SITE_KEY_' . strtoupper($repository_id) ) ?>"
|
24 |
+
<?php endif; ?>
|
25 |
+
>
|
26 |
+
<?php printf(__('Register %s', 'installer'), $generic_product_name); ?>
|
27 |
+
</a>
|
28 |
+
<form class="otgsi_site_key_form" method="post">
|
29 |
+
<input type="hidden" name="action" value="save_site_key" />
|
30 |
+
<input type="hidden" name="nonce" value="<?php echo wp_create_nonce('save_site_key_' . $repository_id) ?>" />
|
31 |
+
<input type="hidden" name="repository_id" value="<?php echo $repository_id ?>">
|
32 |
+
<?php _e('2. Enter your site key', 'installer'); ?>
|
33 |
+
<input type="text" size="10" name="site_key_<?php echo $repository_id ?>" placeholder="<?php echo esc_attr('site key') ?>" />
|
34 |
+
<input class="button-primary" type="submit" value="<?php esc_attr_e('OK', 'installer') ?>" />
|
35 |
+
<input class="button-secondary cancel_site_key_js" type="button" value="<?php esc_attr_e('Cancel', 'installer') ?>" />
|
36 |
+
|
37 |
+
<div class="alignleft" style="margin-top:6px;"><?php printf(__('1. Go to your %s%s account%s and add this site URL: %s', 'installer'),
|
38 |
+
'<a href="' . $this->settings['repositories'][$repository_id]['data']['site_keys_management_url'] . '?add='.urlencode($this->get_installer_site_url( $repository_id )).'">',
|
39 |
+
$generic_product_name, '</a>', $this->get_installer_site_url( $repository_id )); ?></div>
|
40 |
+
</form>
|
41 |
+
|
42 |
+
|
43 |
+
</div>
|
44 |
+
|
45 |
+
<?php
|
46 |
+
$site_key = false;
|
47 |
+
|
48 |
+
// IF SUBSCRIPTION
|
49 |
+
else:
|
50 |
+
|
51 |
+
$site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
|
52 |
+
$subscription_type = $this->get_subscription_type_for_repository($repository_id);
|
53 |
+
$upgrade_options = $this->get_upgrade_options($repository_id);
|
54 |
+
$expired = false;
|
55 |
+
|
56 |
+
?>
|
57 |
+
|
58 |
+
<?php if($this->repository_has_expired_subscription($repository_id)): $expired = true; ?>
|
59 |
+
<div>
|
60 |
+
<p class="installer-warn-box">
|
61 |
+
<?php _e('Subscription expired. You need to either purchase a new subscription or upgrade if available.', 'installer') ?>
|
62 |
+
<span class="alignright">
|
63 |
+
<a class="update_site_key_js button-secondary" href="#" data-repository=<?php echo $repository_id ?> data-nonce="<?php echo wp_create_nonce('update_site_key_' . $repository_id) ?>">
|
64 |
+
<?php _e('Revalidate subscription', 'installer'); ?>
|
65 |
+
</a>
|
66 |
+
</span>
|
67 |
+
<br />
|
68 |
+
<span class="details"><?php _e("If you have already purchased or renewed your subscription and you can still see this message, please revalidate your subscription", 'installer') ?></span>
|
69 |
+
</p>
|
70 |
+
</div>
|
71 |
+
<?php else: ?>
|
72 |
+
<?php $this->show_subscription_renew_warning($repository_id, $subscription_type); ?>
|
73 |
+
<?php endif; ?>
|
74 |
+
|
75 |
+
<div class="alignright">
|
76 |
+
<a class="remove_site_key_js button-secondary" href="#" data-repository=<?php echo $repository_id ?>
|
77 |
+
data-confirmation="<?php esc_attr_e('Are you sure you want to unregister?', 'installer') ?>"
|
78 |
+
data-nonce="<?php echo wp_create_nonce('remove_site_key_' . $repository_id) ?>"
|
79 |
+
<?php if( WP_Installer::get_repository_hardcoded_site_key( $repository_id ) ): ?>
|
80 |
+
style="cursor: help"
|
81 |
+
disabled="disabled"
|
82 |
+
title="<?php printf( esc_attr__("Site-key was set by %s, most likely in wp-config.php. Please remove the constant before attempting to unregister.", 'installer'), 'OTGS_INSTALLER_SITE_KEY_' . strtoupper($repository_id) ) ?>"
|
83 |
+
<?php endif; ?>
|
84 |
+
>
|
85 |
+
<?php printf(__("Unregister %s from this site", 'installer'), $generic_product_name) ?></a>
|
86 |
+
<a class="update_site_key_js button-secondary" href="#" data-repository=<?php echo $repository_id ?>
|
87 |
+
data-nonce="<?php echo wp_create_nonce('update_site_key_' . $repository_id) ?>">
|
88 |
+
<?php _e('Check for updates', 'installer'); ?>
|
89 |
+
</a>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<?php if(empty($expired)): ?>
|
93 |
+
<div class="alignleft">
|
94 |
+
<?php if($expires = $this->settings['repositories'][$repository_id]['subscription']['data']->expires): ?>
|
95 |
+
<?php printf(__('%s is registered on this site. You will receive automatic updates until %s', 'installer'), $generic_product_name, date_i18n('F j, Y', strtotime($expires))); ?>
|
96 |
+
<?php else: ?>
|
97 |
+
<?php printf(__('%s is registered on this site. Your Lifetime account gives you updates for life.', 'installer'), $generic_product_name); ?>
|
98 |
+
<?php endif; ?>
|
99 |
+
</div>
|
100 |
+
<?php endif; //if(empty($expired)) ?>
|
101 |
+
|
102 |
+
<?php endif; // if(!repository_has_subscription) ?>
|
103 |
+
<br clear="all" />
|
104 |
+
<div class="installer-error-box hidden"></div>
|
105 |
+
|
106 |
+
</td>
|
107 |
+
</tr>
|
108 |
+
|
109 |
+
<?php
|
110 |
+
|
111 |
+
$subscription_type = isset($subscription_type) ? $subscription_type : null;
|
112 |
+
$expired = isset($expired) ? $expired : null;
|
113 |
+
$upgrade_options = isset($upgrade_options) ? $upgrade_options : null;
|
114 |
+
$packages = $this->_render_product_packages($repository['data']['packages'], $subscription_type, $expired, $upgrade_options, $repository_id);
|
115 |
+
if(empty($subscription_type) || $expired){
|
116 |
+
$subpackages_expandable = true;
|
117 |
+
}else{
|
118 |
+
$subpackages_expandable = false;
|
119 |
+
}
|
120 |
+
|
121 |
+
?>
|
122 |
+
|
123 |
+
<?php foreach($packages as $package): ?>
|
124 |
+
<tr id="repository-<?php echo $repository_id ?>_<?php echo $package['id'] ?>">
|
125 |
+
<td><img width="140" height="140" src="<?php echo $package['image_url'] ?>" /></td>
|
126 |
+
<td>
|
127 |
+
<p><strong><?php echo $package['name'] ?></strong></p>
|
128 |
+
<p><?php echo $package['description'] ?></p>
|
129 |
+
|
130 |
+
<?php if($package['products']): ?>
|
131 |
+
<?php foreach($package['products'] as $product): ?>
|
132 |
+
<ul class="installer-products-list" style="display:inline">
|
133 |
+
<li>
|
134 |
+
<a class="button-secondary" href="<?php echo $product['url'] ?>"><?php echo $product['label'] ?></a>
|
135 |
+
</li>
|
136 |
+
</ul>
|
137 |
+
<?php endforeach; ?>
|
138 |
+
<?php endif; ?>
|
139 |
+
|
140 |
+
<?php if($package['downloads']): ?>
|
141 |
+
<?php include $this->plugin_path() . '/templates/downloads-list.php'; ?>
|
142 |
+
<?php endif; ?>
|
143 |
+
|
144 |
+
<?php if(!empty($package['sub-packages'])): ?>
|
145 |
+
|
146 |
+
<?php $subpackages = $this->_render_product_packages($package['sub-packages'], $subscription_type, $expired, $upgrade_options, $repository_id); ?>
|
147 |
+
|
148 |
+
<?php if($subpackages): ?>
|
149 |
+
|
150 |
+
<?php if($subpackages_expandable): ?>
|
151 |
+
<h5><a class="installer_expand_button" href="#" title="<?php esc_attr_e('Click to see individual components options.', 'installer') ?>"><?php _e('Individual components', 'installer') ?></a></h5>
|
152 |
+
<?php endif; ?>
|
153 |
+
|
154 |
+
<table class="otgs_wp_installer_subtable" style="<?php if($subpackages_expandable) echo 'display:none' ?>">
|
155 |
+
<?php foreach($subpackages as $package): ?>
|
156 |
+
<tr id="repository-<?php echo $repository_id ?>_<?php echo $package['id'] ?>">
|
157 |
+
<td><img width="70" height="70" src="<?php echo $package['image_url'] ?>" /></td>
|
158 |
+
<td>
|
159 |
+
<p><strong><?php echo $package['name'] ?></strong></p>
|
160 |
+
<p><?php echo $package['description'] ?></p>
|
161 |
+
|
162 |
+
<?php if($package['products']): ?>
|
163 |
+
<?php foreach($package['products'] as $product): ?>
|
164 |
+
<ul class="installer-products-list" style="display:inline">
|
165 |
+
<li>
|
166 |
+
<a class="button-secondary" href="<?php echo $product['url'] ?>"><?php echo $product['label'] ?></a>
|
167 |
+
</li>
|
168 |
+
</ul>
|
169 |
+
<?php endforeach; ?>
|
170 |
+
<?php endif; ?>
|
171 |
+
|
172 |
+
<?php if($package['downloads']): ?>
|
173 |
+
<?php include $this->plugin_path() . '/templates/downloads-list.php'; ?>
|
174 |
+
<?php endif; ?>
|
175 |
+
</td>
|
176 |
+
</tr>
|
177 |
+
<?php endforeach; ?>
|
178 |
+
</table>
|
179 |
+
<?php endif; ?>
|
180 |
+
|
181 |
+
<?php endif; ?>
|
182 |
+
|
183 |
+
|
184 |
+
</td>
|
185 |
+
</tr>
|
186 |
+
|
187 |
+
<?php endforeach; ?>
|
188 |
+
|
189 |
+
</table>
|
190 |
+
|
191 |
+
|
192 |
+
<p><i><?php printf(__('This page lets you install plugins and update existing plugins. To remove any of these plugins, go to the %splugins%s page and if you have the permission to remove plugins you should be able to do this.', 'installer'), '<a href="' . admin_url('plugins.php') . '">' , '</a>'); ?></i></p>
|
193 |
+
|
194 |
+
|
195 |
+
|
196 |
+
<br />
|
library/toolset/types/embedded/frontend.php
CHANGED
@@ -68,7 +68,7 @@ function wpcf_shortcode( $atts, $content = null, $code = '' ) {
|
|
68 |
);
|
69 |
|
70 |
if ( $atts['field'] ) {
|
71 |
-
return types_render_field( $atts['field'], $atts, $content, $code );
|
72 |
}
|
73 |
if ( $atts['termmeta'] ) {
|
74 |
return types_render_termmeta( $atts['termmeta'], $atts, $content, $code );
|
@@ -83,11 +83,15 @@ function wpcf_shortcode( $atts, $content = null, $code = '' ) {
|
|
83 |
/**
|
84 |
* Calls view function for specific field type.
|
85 |
*
|
86 |
-
* @param
|
87 |
-
* @param
|
88 |
-
* @
|
|
|
|
|
|
|
|
|
89 |
*/
|
90 |
-
function types_render_field( $field_id = null, $params = array(), $content = null, $code = '' )
|
91 |
{
|
92 |
if ( empty($field_id) ) {
|
93 |
return '';
|
@@ -101,9 +105,13 @@ function types_render_field( $field_id = null, $params = array(), $content = nul
|
|
101 |
// Set post ID to global
|
102 |
$post_id = get_the_ID();
|
103 |
|
|
|
|
|
|
|
|
|
104 |
// support also 'id' like our shortcode [types] does
|
105 |
// @since 2.1
|
106 |
-
if( ! isset( $params['post_id'] ) && isset( $params['id'] ) &&
|
107 |
$params['post_id'] = $params['id'];
|
108 |
|
109 |
// Check if other post required
|
@@ -367,17 +375,18 @@ function types_render_termmeta( $field_id, $params, $content = null, $code = ''
|
|
367 |
/**
|
368 |
* Calls view function for specific usermeta field type.
|
369 |
*
|
370 |
-
* @
|
|
|
|
|
|
|
371 |
*
|
372 |
-
* @
|
373 |
-
* @
|
374 |
-
* @return type
|
375 |
*/
|
376 |
function types_render_usermeta( $field_id, $params, $content = null, $code = '' ) {
|
377 |
|
378 |
global $wpcf, $post, $wpdb, $WP_Views;
|
379 |
-
|
380 |
-
$html = '';
|
381 |
$current_user = wp_get_current_user();
|
382 |
$current_user_id = $current_user->ID;
|
383 |
|
@@ -392,14 +401,14 @@ function types_render_usermeta( $field_id, $params, $content = null, $code = ''
|
|
392 |
$post_id = $params['post_id'];
|
393 |
}
|
394 |
|
395 |
-
//Get User id from views loop
|
396 |
if (
|
397 |
isset( $WP_Views->users_data['term']->ID )
|
398 |
&& ! empty( $WP_Views->users_data['term']->ID )
|
399 |
) {
|
400 |
$params['user_id'] = $WP_Views->users_data['term']->ID;
|
401 |
}
|
402 |
-
|
403 |
//Get user By ID
|
404 |
if ( isset( $params['user_id'] ) ) {
|
405 |
$user_id = $params['user_id'];
|
@@ -418,13 +427,14 @@ function types_render_usermeta( $field_id, $params, $content = null, $code = ''
|
|
418 |
if ( !empty( $post_id ) ) {
|
419 |
$user_id = $post->post_author;
|
420 |
} else {
|
421 |
-
return;
|
422 |
}
|
423 |
}
|
424 |
|
425 |
if ( empty( $user_id ) ) {
|
426 |
-
return;
|
427 |
}
|
|
|
428 |
// Get field
|
429 |
$field = types_get_field( $field_id, 'usermeta' );
|
430 |
|
@@ -442,27 +452,18 @@ function types_render_usermeta( $field_id, $params, $content = null, $code = ''
|
|
442 |
return '';
|
443 |
}
|
444 |
|
445 |
-
|
446 |
-
if ( wpcf_admin_is_repetitive( $field ) ) {
|
447 |
|
448 |
$wpcf->usermeta_repeater->set( $user_id, $field );
|
449 |
$_meta = $wpcf->usermeta_repeater->_get_meta();
|
450 |
-
$meta = '';
|
451 |
-
if ( isset( $_meta['custom_order'] ) ) {
|
452 |
-
$meta = $_meta['custom_order'];
|
453 |
-
}
|
454 |
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
$params['field_value'] = $_temp;
|
462 |
-
return types_render_field_single( $field, $params, $content,
|
463 |
-
$code, $meta_id );
|
464 |
-
}
|
465 |
-
} else if ( !empty( $meta ) ) {
|
466 |
$output = '';
|
467 |
|
468 |
if ( isset( $params['index'] ) ) {
|
@@ -524,9 +525,13 @@ function types_render_usermeta( $field_id, $params, $content = null, $code = ''
|
|
524 |
/**
|
525 |
* Calls view function for specific field type by single field.
|
526 |
*
|
527 |
-
* @param
|
528 |
-
* @param
|
529 |
-
* @
|
|
|
|
|
|
|
|
|
530 |
*/
|
531 |
function types_render_field_single( $field, $params, $content = null, $code = '', $meta_id = null )
|
532 |
{
|
68 |
);
|
69 |
|
70 |
if ( $atts['field'] ) {
|
71 |
+
return types_render_field( $atts['field'], $atts, $content, $code, false );
|
72 |
}
|
73 |
if ( $atts['termmeta'] ) {
|
74 |
return types_render_termmeta( $atts['termmeta'], $atts, $content, $code );
|
83 |
/**
|
84 |
* Calls view function for specific field type.
|
85 |
*
|
86 |
+
* @param null|integer $field_id
|
87 |
+
* @param array $params
|
88 |
+
* @param null|string $content
|
89 |
+
* @param string $code
|
90 |
+
* @param bool $block_parent Used by the shortcode [types] which already change the global post before calling this
|
91 |
+
*
|
92 |
+
* @return string
|
93 |
*/
|
94 |
+
function types_render_field( $field_id = null, $params = array(), $content = null, $code = '', $allow_parent = true )
|
95 |
{
|
96 |
if ( empty($field_id) ) {
|
97 |
return '';
|
105 |
// Set post ID to global
|
106 |
$post_id = get_the_ID();
|
107 |
|
108 |
+
// check if "$parent" for "id" is allowed
|
109 |
+
// OR if "id" does not contain a "$parent" selection
|
110 |
+
$parent_check = isset( $params['id'] ) && ( $allow_parent || substr( $params['id'], 0, 1) !== '$' );
|
111 |
+
|
112 |
// support also 'id' like our shortcode [types] does
|
113 |
// @since 2.1
|
114 |
+
if( ! isset( $params['post_id'] ) && isset( $params['id'] ) && $parent_check )
|
115 |
$params['post_id'] = $params['id'];
|
116 |
|
117 |
// Check if other post required
|
375 |
/**
|
376 |
* Calls view function for specific usermeta field type.
|
377 |
*
|
378 |
+
* @param $field_id
|
379 |
+
* @param array $params (additional attributes: user_id, user_name, user_is_author, user_current)
|
380 |
+
* @param null $content
|
381 |
+
* @param string $code
|
382 |
*
|
383 |
+
* @return string|void
|
384 |
+
* @since unknown
|
|
|
385 |
*/
|
386 |
function types_render_usermeta( $field_id, $params, $content = null, $code = '' ) {
|
387 |
|
388 |
global $wpcf, $post, $wpdb, $WP_Views;
|
389 |
+
|
|
|
390 |
$current_user = wp_get_current_user();
|
391 |
$current_user_id = $current_user->ID;
|
392 |
|
401 |
$post_id = $params['post_id'];
|
402 |
}
|
403 |
|
404 |
+
// Get User id from views loop
|
405 |
if (
|
406 |
isset( $WP_Views->users_data['term']->ID )
|
407 |
&& ! empty( $WP_Views->users_data['term']->ID )
|
408 |
) {
|
409 |
$params['user_id'] = $WP_Views->users_data['term']->ID;
|
410 |
}
|
411 |
+
|
412 |
//Get user By ID
|
413 |
if ( isset( $params['user_id'] ) ) {
|
414 |
$user_id = $params['user_id'];
|
427 |
if ( !empty( $post_id ) ) {
|
428 |
$user_id = $post->post_author;
|
429 |
} else {
|
430 |
+
return '';
|
431 |
}
|
432 |
}
|
433 |
|
434 |
if ( empty( $user_id ) ) {
|
435 |
+
return '';
|
436 |
}
|
437 |
+
|
438 |
// Get field
|
439 |
$field = types_get_field( $field_id, 'usermeta' );
|
440 |
|
452 |
return '';
|
453 |
}
|
454 |
|
455 |
+
if ( types_is_repetitive( $field ) ) {
|
|
|
456 |
|
457 |
$wpcf->usermeta_repeater->set( $user_id, $field );
|
458 |
$_meta = $wpcf->usermeta_repeater->_get_meta();
|
459 |
+
$meta = toolset_getarr( $_meta, 'custom_order', '' );
|
|
|
|
|
|
|
460 |
|
461 |
+
// Sometimes if meta is empty - array(0 => '') is returned
|
462 |
+
if ( count( $meta ) == 1 && reset( $meta ) == '' ) {
|
463 |
+
return '';
|
464 |
+
}
|
465 |
+
|
466 |
+
if ( !empty( $meta ) ) {
|
|
|
|
|
|
|
|
|
|
|
467 |
$output = '';
|
468 |
|
469 |
if ( isset( $params['index'] ) ) {
|
525 |
/**
|
526 |
* Calls view function for specific field type by single field.
|
527 |
*
|
528 |
+
* @param array $field
|
529 |
+
* @param array $params
|
530 |
+
* @param mixed $content
|
531 |
+
* @param string $code
|
532 |
+
* @param null|int $meta_id
|
533 |
+
*
|
534 |
+
* @return string
|
535 |
*/
|
536 |
function types_render_field_single( $field, $params, $content = null, $code = '', $meta_id = null )
|
537 |
{
|
library/toolset/types/embedded/includes/api.php
CHANGED
@@ -150,8 +150,9 @@ function types_field_get_meta_value_repetitive( $field, $post_id = null,
|
|
150 |
/**
|
151 |
* Check if field is repetitive.
|
152 |
*
|
153 |
-
* @param
|
154 |
-
* @return
|
|
|
155 |
*/
|
156 |
function types_is_repetitive( $field ) {
|
157 |
|
@@ -159,7 +160,7 @@ function types_is_repetitive( $field ) {
|
|
159 |
if ( !is_array( $field ) ) {
|
160 |
$field = types_get_field( $field );
|
161 |
if ( empty( $field ) ) {
|
162 |
-
return
|
163 |
}
|
164 |
}
|
165 |
|
150 |
/**
|
151 |
* Check if field is repetitive.
|
152 |
*
|
153 |
+
* @param array|string $field Field definition or field slug
|
154 |
+
* @return bool|null
|
155 |
+
* @since unknown
|
156 |
*/
|
157 |
function types_is_repetitive( $field ) {
|
158 |
|
160 |
if ( !is_array( $field ) ) {
|
161 |
$field = types_get_field( $field );
|
162 |
if ( empty( $field ) ) {
|
163 |
+
return null;
|
164 |
}
|
165 |
}
|
166 |
|
library/toolset/types/embedded/includes/custom-taxonomies.php
CHANGED
@@ -139,96 +139,124 @@ function wpcf_taxonomies_register($taxonomy, $data)
|
|
139 |
/**
|
140 |
* Registers custom taxonomies.
|
141 |
*
|
142 |
-
* @param
|
143 |
-
* @param
|
|
|
|
|
|
|
144 |
*/
|
145 |
function wpcf_custom_taxonomies_register( $taxonomy, $data ) {
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
}
|
227 |
|
|
|
228 |
/**
|
229 |
* Returns only active taxonomies.
|
230 |
*
|
231 |
-
* @return
|
232 |
*/
|
233 |
function wpcf_get_active_custom_taxonomies() {
|
234 |
$taxonomies = get_option(WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array());
|
139 |
/**
|
140 |
* Registers custom taxonomies.
|
141 |
*
|
142 |
+
* @param string $taxonomy Taxonomy slug
|
143 |
+
* @param array $data Taxonomy settings as stored in options by Types.
|
144 |
+
*
|
145 |
+
* @return bool
|
146 |
+
* @since unknown
|
147 |
*/
|
148 |
function wpcf_custom_taxonomies_register( $taxonomy, $data ) {
|
149 |
+
if ( ! empty( $data['disabled'] ) ) {
|
150 |
+
return false;
|
151 |
+
}
|
152 |
+
|
153 |
+
// Set object types
|
154 |
+
if ( ! empty( $data['supports'] ) && is_array( $data['supports'] ) ) {
|
155 |
+
$object_types = array_keys( $data['supports'] );
|
156 |
+
} else {
|
157 |
+
$object_types = array();
|
158 |
+
}
|
159 |
+
|
160 |
+
$data = apply_filters( 'types_taxonomy', $data, $taxonomy );
|
161 |
+
|
162 |
+
// Set labels
|
163 |
+
if ( ! empty( $data['labels'] ) ) {
|
164 |
+
|
165 |
+
if ( ! isset( $data['labels']['name'] ) ) {
|
166 |
+
$data['labels']['name'] = $taxonomy;
|
167 |
+
}
|
168 |
+
|
169 |
+
if ( ! isset( $data['labels']['singular_name'] ) ) {
|
170 |
+
$data['labels']['singular_name'] = $data['labels']['name'];
|
171 |
+
}
|
172 |
+
|
173 |
+
foreach ( $data['labels'] as $label_key => $label ) {
|
174 |
+
$data['labels'][ $label_key ] = $label = stripslashes( $label );
|
175 |
+
|
176 |
+
switch ( $label_key ) {
|
177 |
+
|
178 |
+
case 'parent_item':
|
179 |
+
case 'parent_item_colon':
|
180 |
+
case 'edit_item':
|
181 |
+
case 'update_item':
|
182 |
+
case 'add_new_item':
|
183 |
+
case 'new_item_name':
|
184 |
+
$data['labels'][ $label_key ] = sprintf( $label, $data['labels']['singular_name'] );
|
185 |
+
break;
|
186 |
+
|
187 |
+
case 'search_items':
|
188 |
+
case 'popular_items':
|
189 |
+
case 'all_items':
|
190 |
+
case 'separate_items_with_commas':
|
191 |
+
case 'add_or_remove_items':
|
192 |
+
case 'choose_from_most_used':
|
193 |
+
case 'menu_name':
|
194 |
+
$data['labels'][ $label_key ] = sprintf( $label, $data['labels']['name'] );
|
195 |
+
break;
|
196 |
+
}
|
197 |
+
}
|
198 |
+
}
|
199 |
+
|
200 |
+
$data['description'] = (
|
201 |
+
! empty( $data['description'] )
|
202 |
+
? htmlspecialchars( stripslashes( $data['description'] ), ENT_QUOTES )
|
203 |
+
: ''
|
204 |
+
);
|
205 |
+
|
206 |
+
$data['public'] = ( empty( $data['public'] ) || strval( $data['public'] ) == 'hidden' ) ? false : true;
|
207 |
+
$data['show_ui'] = ( empty( $data['show_ui'] ) || ! $data['public'] ) ? false : true;
|
208 |
+
$data['hierarchical'] = ( empty( $data['hierarchical'] ) || $data['hierarchical'] == 'flat' ) ? false : true;
|
209 |
+
$data['show_in_nav_menus'] = ! empty( $data['show_in_nav_menus'] );
|
210 |
+
|
211 |
+
if ( empty( $data['query_var_enabled'] ) ) {
|
212 |
+
$data['query_var'] = false;
|
213 |
+
} else if ( empty( $data['query_var'] ) ) {
|
214 |
+
$data['query_var'] = true;
|
215 |
+
}
|
216 |
+
|
217 |
+
if ( ! empty( $data['rewrite']['enabled'] ) ) {
|
218 |
+
$data['rewrite']['with_front'] = ! empty( $data['rewrite']['with_front'] );
|
219 |
+
$data['rewrite']['hierarchical'] = ! empty( $data['rewrite']['hierarchical'] );
|
220 |
+
// Make sure that rewrite/slug has a value
|
221 |
+
if ( ! isset( $data['rewrite']['slug'] ) || $data['rewrite']['slug'] == '' ) {
|
222 |
+
$data['rewrite']['slug'] = $data['slug'];
|
223 |
+
}
|
224 |
+
} else {
|
225 |
+
$data['rewrite'] = false;
|
226 |
+
}
|
227 |
+
|
228 |
+
// meta_box_cb
|
229 |
+
if ( isset( $data['meta_box_cb']['disabled'] ) ) {
|
230 |
+
$data['meta_box_cb'] = false;
|
231 |
+
} else if ( isset( $data['meta_box_cb']['callback'] ) && ! empty( $data['meta_box_cb']['callback'] ) ) {
|
232 |
+
$data['meta_box_cb'] = $data['meta_box_cb']['callback'];
|
233 |
+
} else {
|
234 |
+
unset( $data['meta_box_cb'] );
|
235 |
+
}
|
236 |
+
|
237 |
+
// Force removing capabilities here
|
238 |
+
unset( $data['capabilities'] );
|
239 |
+
|
240 |
+
$object_types_filtered = apply_filters( 'wpcf_taxonomy_objects', $object_types, $taxonomy );
|
241 |
+
$taxonomy_args = apply_filters( 'wpcf_taxonomy_data', $data, $taxonomy, $object_types );
|
242 |
+
|
243 |
+
// Suddenly, WordPress 4.7 (alpha) requires the 'name' argument and uses it as the slug.
|
244 |
+
if ( ( ! isset( $taxonomy_args['name'] ) ) || false == $taxonomy_args['name'] ) {
|
245 |
+
$taxonomy_args['name'] = $taxonomy;
|
246 |
+
}
|
247 |
+
|
248 |
+
$result = register_taxonomy( $taxonomy, $object_types_filtered, $taxonomy_args );
|
249 |
+
|
250 |
+
$is_success = ( $result instanceof WP_Error ? false : true );
|
251 |
+
|
252 |
+
return $is_success;
|
253 |
}
|
254 |
|
255 |
+
|
256 |
/**
|
257 |
* Returns only active taxonomies.
|
258 |
*
|
259 |
+
* @return array
|
260 |
*/
|
261 |
function wpcf_get_active_custom_taxonomies() {
|
262 |
$taxonomies = get_option(WPCF_OPTION_NAME_CUSTOM_TAXONOMIES, array());
|
library/toolset/types/embedded/includes/fields-post.php
CHANGED
@@ -217,18 +217,20 @@ function wpcf_add_meta_boxes( $post_type, $post )
|
|
217 |
|
218 |
// Check if hidden
|
219 |
if ( !isset( $group['__show_meta_box'] ) || $group['__show_meta_box'] != false ) {
|
|
|
|
|
|
|
220 |
// Add meta boxes
|
221 |
if ( empty( $only_preview ) ) {
|
222 |
add_meta_box( "wpcf-group-{$group['slug']}",
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
} else {
|
227 |
add_meta_box( "wpcf-group-{$group['slug']}",
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
$group['meta_box_context'], 'high', $group );
|
232 |
}
|
233 |
}
|
234 |
}
|
@@ -407,6 +409,7 @@ function wpcf_admin_post_meta_box_preview( $post, $group, $echo = '' ){
|
|
407 |
*/
|
408 |
function wpcf_admin_post_meta_box( $post, $group, $echo = '', $open_style_editor = false )
|
409 |
{
|
|
|
410 |
|
411 |
if (
|
412 |
false === $open_style_editor
|
@@ -418,7 +421,7 @@ function wpcf_admin_post_meta_box( $post, $group, $echo = '', $open_style_editor
|
|
418 |
*/
|
419 |
if ( array_key_exists('description', $group['args'] ) && !empty($group['args']['description'])) {
|
420 |
echo '<div class="wpcf-meta-box-description">';
|
421 |
-
echo wpautop(
|
422 |
echo '</div>';
|
423 |
}
|
424 |
foreach ( $group['args']['html'] as $field ) {
|
@@ -487,8 +490,7 @@ function wpcf_admin_post_meta_box( $post, $group, $echo = '', $open_style_editor
|
|
487 |
// Display description
|
488 |
if ( !empty( $group['args']['description'] ) ) {
|
489 |
$group_output .= '<div class="wpcf-meta-box-description">'
|
490 |
-
. wpautop(
|
491 |
-
$group['args']['description'] ) ) . '</div>';
|
492 |
}
|
493 |
foreach ( $group['args']['fields'] as $field_slug => $field ) {
|
494 |
if ( empty( $field ) || !is_array( $field ) ) {
|
217 |
|
218 |
// Check if hidden
|
219 |
if ( !isset( $group['__show_meta_box'] ) || $group['__show_meta_box'] != false ) {
|
220 |
+
|
221 |
+
$group_wpml = new Types_Wpml_Field_Group( Types_Field_Group_Post_Factory::load( $group['slug'] ) );
|
222 |
+
|
223 |
// Add meta boxes
|
224 |
if ( empty( $only_preview ) ) {
|
225 |
add_meta_box( "wpcf-group-{$group['slug']}",
|
226 |
+
$group_wpml->translate_name(),
|
227 |
+
'wpcf_admin_post_meta_box',
|
228 |
+
$post_type, $group['meta_box_context'], 'high', $group );
|
229 |
} else {
|
230 |
add_meta_box( "wpcf-group-{$group['slug']}",
|
231 |
+
$group_wpml->translate_name(),
|
232 |
+
'wpcf_admin_post_meta_box_preview', $post_type,
|
233 |
+
$group['meta_box_context'], 'high', $group );
|
|
|
234 |
}
|
235 |
}
|
236 |
}
|
409 |
*/
|
410 |
function wpcf_admin_post_meta_box( $post, $group, $echo = '', $open_style_editor = false )
|
411 |
{
|
412 |
+
$group_wpml = new Types_Wpml_Field_Group( Types_Field_Group_Post_Factory::load( $group['args']['slug'] ) );
|
413 |
|
414 |
if (
|
415 |
false === $open_style_editor
|
421 |
*/
|
422 |
if ( array_key_exists('description', $group['args'] ) && !empty($group['args']['description'])) {
|
423 |
echo '<div class="wpcf-meta-box-description">';
|
424 |
+
echo wpautop( $group_wpml->translate_description() );
|
425 |
echo '</div>';
|
426 |
}
|
427 |
foreach ( $group['args']['html'] as $field ) {
|
490 |
// Display description
|
491 |
if ( !empty( $group['args']['description'] ) ) {
|
492 |
$group_output .= '<div class="wpcf-meta-box-description">'
|
493 |
+
. wpautop( $group_wpml->translate_description() ) . '</div>';
|
|
|
494 |
}
|
495 |
foreach ( $group['args']['fields'] as $field_slug => $field ) {
|
496 |
if ( empty( $field ) || !is_array( $field ) ) {
|
library/toolset/types/embedded/includes/fields.php
CHANGED
@@ -253,6 +253,64 @@ function wpcf_admin_fields_get_fields( $only_active = false,
|
|
253 |
return $cache[$cache_key];
|
254 |
}
|
255 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
function wpcf_admin_fields_get_field_by_meta_key( $meta_key )
|
257 |
{
|
258 |
$fields = wpcf_admin_fields_get_fields();
|
253 |
return $cache[$cache_key];
|
254 |
}
|
255 |
|
256 |
+
|
257 |
+
add_filter( 'types_fields', 'wpcf_add_mandatory_validation_rules' );
|
258 |
+
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Modify field definitions when they are being loaded from the database.
|
262 |
+
*
|
263 |
+
* Hooked into types_fields. Not to be used elsewhere.
|
264 |
+
*
|
265 |
+
* Add mandatory validation rules that have not been stored in the database but are needed by Types and toolset-forms
|
266 |
+
* to work properly. Namely it's the URL validation for file fields. CRED handles these fields in its own way (front-end
|
267 |
+
* file upload), so this is a Types-specific problem.
|
268 |
+
*
|
269 |
+
* @param array $field_definitions An associative array of field definition arrays with field slugs as keys.
|
270 |
+
* @return array
|
271 |
+
* @since 2.2.4
|
272 |
+
*/
|
273 |
+
function wpcf_add_mandatory_validation_rules( $field_definitions ) {
|
274 |
+
|
275 |
+
if( is_array( $field_definitions ) ) {
|
276 |
+
foreach( $field_definitions as $field_slug => $field_definition ) {
|
277 |
+
|
278 |
+
// Add URL validation to file fields (containing URLs).
|
279 |
+
//
|
280 |
+
// This doesn't include embed files because they are more variable and the URL validation can be
|
281 |
+
// configured on the Edit Field Group page.
|
282 |
+
$file_fields = array( 'file', 'image', 'audio', 'video' );
|
283 |
+
|
284 |
+
$field_type = toolset_getarr( $field_definition, 'type' );
|
285 |
+
$is_file_field = in_array( $field_type, $file_fields );
|
286 |
+
$validation_rules = wpcf_ensarr( wpcf_getnest( $field_definition, array( 'data', 'validate' ) ) );
|
287 |
+
$has_url_validation = array_key_exists( 'url', $validation_rules );
|
288 |
+
|
289 |
+
if( $is_file_field && ! $has_url_validation ) {
|
290 |
+
|
291 |
+
$default_validation_error_message = __( 'Please enter a valid URL address pointing to the file.', 'wpcf' );
|
292 |
+
$validation_error_messages = array(
|
293 |
+
'file' => $default_validation_error_message,
|
294 |
+
'audio' => __( 'Please enter a valid URL address pointing to the audio file.', 'wpcf' ),
|
295 |
+
'image' => __( 'Please enter a valid URL address pointing to the image file.', 'wpcf' ),
|
296 |
+
'video' => __( 'Please enter a valid URL address pointing to the video file.', 'wpcf' )
|
297 |
+
);
|
298 |
+
|
299 |
+
$validation_rules['url'] = array(
|
300 |
+
'active' => '1',
|
301 |
+
'message' => toolset_getarr( $validation_error_messages, $field_type, $default_validation_error_message )
|
302 |
+
);
|
303 |
+
|
304 |
+
$field_definitions[ $field_slug ]['data']['validate'] = $validation_rules;
|
305 |
+
}
|
306 |
+
}
|
307 |
+
}
|
308 |
+
|
309 |
+
return $field_definitions;
|
310 |
+
}
|
311 |
+
|
312 |
+
|
313 |
+
|
314 |
function wpcf_admin_fields_get_field_by_meta_key( $meta_key )
|
315 |
{
|
316 |
$fields = wpcf_admin_fields_get_fields();
|
library/toolset/types/embedded/includes/fields/wysiwyg.php
CHANGED
@@ -179,18 +179,32 @@ function wpcf_fields_wysiwyg_view( $params ) {
|
|
179 |
}
|
180 |
|
181 |
/**
|
182 |
-
*
|
|
|
|
|
|
|
|
|
|
|
183 |
*
|
184 |
* @since 1.9.1
|
|
|
185 |
*/
|
186 |
-
|
187 |
class WPCF_WP_filter_state {
|
188 |
|
189 |
private $current_index;
|
190 |
private $tag;
|
|
|
191 |
|
192 |
public function __construct( $tag ) {
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
|
195 |
$this->tag = $tag;
|
196 |
|
@@ -200,6 +214,11 @@ class WPCF_WP_filter_state {
|
|
200 |
}
|
201 |
|
202 |
public function restore( ) {
|
|
|
|
|
|
|
|
|
|
|
203 |
global $wp_filter;
|
204 |
|
205 |
if ( isset( $wp_filter[$this->tag] ) && $this->current_index ) {
|
@@ -211,4 +230,4 @@ class WPCF_WP_filter_state {
|
|
211 |
|
212 |
}
|
213 |
|
214 |
-
}
|
179 |
}
|
180 |
|
181 |
/**
|
182 |
+
* Used for recording a current item of the callbacks in $wp_filter[ $tag ] and restoring it
|
183 |
+
* after applying a filter recursively.
|
184 |
+
*
|
185 |
+
* Workaround for https://core.trac.wordpress.org/ticket/17817.
|
186 |
+
*
|
187 |
+
* From WordPress 4.7 above, this does nothing.
|
188 |
*
|
189 |
* @since 1.9.1
|
190 |
+
* @deprecated No longer needed since WordPress 4.7
|
191 |
*/
|
|
|
192 |
class WPCF_WP_filter_state {
|
193 |
|
194 |
private $current_index;
|
195 |
private $tag;
|
196 |
+
private $is_disabled = false;
|
197 |
|
198 |
public function __construct( $tag ) {
|
199 |
+
|
200 |
+
global $wp_version;
|
201 |
+
|
202 |
+
if( version_compare( $wp_version, '4.6.9', '>' ) ) {
|
203 |
+
$this->is_disabled = true;
|
204 |
+
return;
|
205 |
+
}
|
206 |
+
|
207 |
+
global $wp_filter;
|
208 |
|
209 |
$this->tag = $tag;
|
210 |
|
214 |
}
|
215 |
|
216 |
public function restore( ) {
|
217 |
+
|
218 |
+
if( $this->is_disabled ) {
|
219 |
+
return;
|
220 |
+
}
|
221 |
+
|
222 |
global $wp_filter;
|
223 |
|
224 |
if ( isset( $wp_filter[$this->tag] ) && $this->current_index ) {
|
230 |
|
231 |
}
|
232 |
|
233 |
+
}
|
library/toolset/types/embedded/includes/module-manager.php
CHANGED
@@ -661,6 +661,7 @@ function wpcf_admin_export_selected_data ( array $items, $_type = 'all', $return
|
|
661 |
if( isset( $type['custom-field-group'] )
|
662 |
&& is_array( $type['custom-field-group'] )
|
663 |
&& !empty( $type['custom-field-group'] ) ) {
|
|
|
664 |
foreach( $type['custom-field-group'] as $custom_field_group_id => $senseless_as_it_is_always_one ) {
|
665 |
$custom_field_group = get_post( $custom_field_group_id );
|
666 |
|
@@ -671,8 +672,8 @@ function wpcf_admin_export_selected_data ( array $items, $_type = 'all', $return
|
|
671 |
if( !is_object( $custom_field_group ) )
|
672 |
continue;
|
673 |
|
674 |
-
// set custom field
|
675 |
-
$custom_types[$key]['custom-field-group'][$
|
676 |
}
|
677 |
}
|
678 |
|
@@ -742,9 +743,8 @@ function wpcf_admin_export_selected_data ( array $items, $_type = 'all', $return
|
|
742 |
}
|
743 |
if ( !empty( $custom_taxonomies ) ) {
|
744 |
foreach ( $custom_taxonomies as $key => $tax ) {
|
745 |
-
|
746 |
$custom_taxonomies[$key] = apply_filters( 'wpcf_filter_export_custom_taxonomy', $custom_taxonomies[$key] );
|
747 |
-
|
748 |
$custom_taxonomies[$key]['__types_id'] = $key;
|
749 |
$custom_taxonomies[$key]['__types_title'] = $tax['labels']['name'];
|
750 |
$custom_taxonomies[$key]['checksum'] = $wpcf->export->generate_checksum(
|
@@ -1320,28 +1320,44 @@ function wpcf_modman_set_submitted_id( $set, $id ) {
|
|
1320 |
return '12' . $set . '21' . $id;
|
1321 |
}
|
1322 |
|
|
|
|
|
|
|
|
|
1323 |
/**
|
1324 |
-
*
|
1325 |
-
*
|
1326 |
-
*
|
1327 |
-
*
|
1328 |
-
*
|
1329 |
-
*
|
1330 |
-
*
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
-
|
1339 |
-
|
1340 |
-
|
1341 |
-
|
1342 |
-
|
1343 |
-
|
1344 |
-
}
|
1345 |
}
|
1346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1347 |
}
|
661 |
if( isset( $type['custom-field-group'] )
|
662 |
&& is_array( $type['custom-field-group'] )
|
663 |
&& !empty( $type['custom-field-group'] ) ) {
|
664 |
+
|
665 |
foreach( $type['custom-field-group'] as $custom_field_group_id => $senseless_as_it_is_always_one ) {
|
666 |
$custom_field_group = get_post( $custom_field_group_id );
|
667 |
|
672 |
if( !is_object( $custom_field_group ) )
|
673 |
continue;
|
674 |
|
675 |
+
// set custom field, generating an unique key (but without a particular meaning) AND ID AS VALUE to custom post type
|
676 |
+
$custom_types[ $key ]['custom-field-group'][ 'group_' . $custom_field_group_id ] = $custom_field_group_id;
|
677 |
}
|
678 |
}
|
679 |
|
743 |
}
|
744 |
if ( !empty( $custom_taxonomies ) ) {
|
745 |
foreach ( $custom_taxonomies as $key => $tax ) {
|
746 |
+
$custom_taxonomies[$key]['id'] = $key;
|
747 |
$custom_taxonomies[$key] = apply_filters( 'wpcf_filter_export_custom_taxonomy', $custom_taxonomies[$key] );
|
|
|
748 |
$custom_taxonomies[$key]['__types_id'] = $key;
|
749 |
$custom_taxonomies[$key]['__types_title'] = $tax['labels']['name'];
|
750 |
$custom_taxonomies[$key]['checksum'] = $wpcf->export->generate_checksum(
|
1320 |
return '12' . $set . '21' . $id;
|
1321 |
}
|
1322 |
|
1323 |
+
|
1324 |
+
add_filter( 'wpcf_filter_export_custom_taxonomy', 'wpcf_fix_exported_taxonomy_assignment_to_cpt' );
|
1325 |
+
|
1326 |
+
|
1327 |
/**
|
1328 |
+
* Filter the data to be exported for custom taxonomies.
|
1329 |
+
*
|
1330 |
+
* Ensure the settings of post types associated with the taxonomy is exported correctly, even with support of legacy
|
1331 |
+
* settings.
|
1332 |
+
*
|
1333 |
+
* @param array $taxonomy_data
|
1334 |
+
* @return array Modified taxonomy data.
|
1335 |
+
* @since unknown
|
1336 |
+
*/
|
1337 |
+
function wpcf_fix_exported_taxonomy_assignment_to_cpt( $taxonomy_data = array() ) {
|
1338 |
+
|
1339 |
+
$setting_name_prefix = '__types_cpt_supports_';
|
1340 |
+
$post_type_support_settings = array();
|
1341 |
+
|
1342 |
+
// Associated CPTs slugs are stored as XML keys, so they can not start with a number.
|
1343 |
+
// We force a prefix on all of them on export, and restore them on import.
|
1344 |
+
$supported_post_types = wpcf_ensarr( wpcf_getarr( $taxonomy_data, 'supports' ) );
|
1345 |
+
foreach( $supported_post_types as $post_type_slug => $is_supported ) {
|
1346 |
+
$setting_name = $setting_name_prefix . $post_type_slug;
|
1347 |
+
$post_type_support_settings[ $setting_name ] = ( $is_supported ? 1 : 0 );
|
|
|
1348 |
}
|
1349 |
+
|
1350 |
+
// Here, we will also process the legacy "object_type" setting, containing supported post type slugs as array items,
|
1351 |
+
// in the samve way.
|
1352 |
+
$legacy_supported_post_type_array = wpcf_ensarr( wpcf_getarr( $taxonomy_data, 'object_type' ) );
|
1353 |
+
foreach( $legacy_supported_post_type_array as $post_type_slug ) {
|
1354 |
+
$setting_name = $setting_name_prefix . $post_type_slug;
|
1355 |
+
$post_type_support_settings[ $setting_name ] = 1;
|
1356 |
+
}
|
1357 |
+
|
1358 |
+
// Now we need to remove this legacy setting to prevent producing invalid XML.
|
1359 |
+
unset( $taxonomy_data['object_type'] );
|
1360 |
+
|
1361 |
+
$taxonomy_data['supports'] = $post_type_support_settings;
|
1362 |
+
return $taxonomy_data;
|
1363 |
}
|
library/toolset/types/embedded/includes/post-relationship.php
CHANGED
@@ -5,7 +5,37 @@
|
|
5 |
*
|
6 |
*/
|
7 |
add_action( 'wpcf_admin_post_init', 'wpcf_pr_admin_post_init_action', 10, 4 );
|
|
|
8 |
add_action( 'save_post', 'wpcf_pr_admin_save_post_hook', 20, 2 ); // Trigger afer main hook
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
if ( is_admin() ) {
|
10 |
add_action('wp_ajax_wpcf_relationship_search', 'wpcf_pr_admin_wpcf_relationship_search');
|
11 |
// Deprecated since the introduction of select v.4
|
@@ -94,37 +124,51 @@ function wpcf_pr_admin_post_init_action( $post_type, $post, $groups, $wpcf_activ
|
|
94 |
}
|
95 |
}
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
/**
|
98 |
* Gets post types that belong to current post type.
|
99 |
*
|
100 |
-
* @param
|
101 |
-
* @return
|
102 |
*/
|
103 |
-
function wpcf_pr_admin_get_has( $
|
104 |
static $cache = array();
|
105 |
-
if ( isset( $cache[$
|
106 |
-
return $cache[$
|
107 |
}
|
108 |
$relationships = get_option( 'wpcf_post_relationship', array() );
|
109 |
-
if ( empty( $relationships[$
|
110 |
return false;
|
111 |
}
|
112 |
// See if enabled
|
113 |
-
foreach ( $relationships[$
|
114 |
-
|
115 |
-
|
116 |
-
unset( $relationships[$post_type][$temp_post_type] );
|
117 |
}
|
118 |
}
|
119 |
-
$cache[$
|
120 |
-
return $cache[$
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
* Gets post types that current post type belongs to.
|
125 |
*
|
126 |
-
* @param
|
127 |
-
* @return
|
128 |
*/
|
129 |
function wpcf_pr_admin_get_belongs( $post_type ) {
|
130 |
static $cache = array();
|
@@ -135,11 +179,11 @@ function wpcf_pr_admin_get_belongs( $post_type ) {
|
|
135 |
$results = array();
|
136 |
if ( is_array( $relationships ) ) {
|
137 |
foreach ( $relationships as $has => $belongs ) {
|
138 |
-
|
139 |
-
|
140 |
-
if ( !$active ) {
|
141 |
continue;
|
142 |
}
|
|
|
143 |
if ( array_key_exists( $post_type, $belongs ) ) {
|
144 |
$results[$has] = $belongs[$post_type];
|
145 |
}
|
@@ -346,15 +390,61 @@ function wpcf_pr_admin_post_meta_box_belongs_form( $post, $type, $belongs )
|
|
346 |
$id = esc_attr(sprintf('wpcf_pr_belongs_%d_%s', $post->ID, $type));
|
347 |
$belongs_id = isset( $belongs['belongs'][$type] ) ? $belongs['belongs'][$type] : 0;
|
348 |
|
349 |
-
$options_array
|
350 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
351 |
if ( $belongs_id ) {
|
|
|
|
|
352 |
$options_array[ $belongs_id ] = array(
|
353 |
'#title' => get_the_title( $belongs_id ),
|
354 |
'#value' => $belongs_id,
|
355 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
}
|
357 |
|
|
|
358 |
$form[$type] = array(
|
359 |
'#type' => 'select',
|
360 |
'#name' => 'wpcf_pr_belongs[' . $post->ID . '][' . $type . ']',
|
@@ -368,30 +458,9 @@ function wpcf_pr_admin_post_meta_box_belongs_form( $post, $type, $belongs )
|
|
368 |
'data-placeholder' => esc_attr( sprintf( __('Search for %s', 'wpcf'), $temp_type->labels->name ) ),
|
369 |
'data-post-id' => $post->ID,
|
370 |
'data-post-type' => esc_attr($type),
|
|
|
371 |
),
|
372 |
);
|
373 |
-
|
374 |
-
/*
|
375 |
-
$form[$type] = array(
|
376 |
-
'#type' => 'textfield',
|
377 |
-
'#name' => 'wpcf_pr_belongs[' . $post->ID . '][' . $type . ']',
|
378 |
-
'#value' => isset( $belongs['belongs'][$type] ) ? $belongs['belongs'][$type] : 0,
|
379 |
-
'#id' => $id,
|
380 |
-
'#attributes' => array(
|
381 |
-
'class' => 'wpcf-pr-belongs',
|
382 |
-
'data-loading' => esc_attr__('Please Wait, Loading…', 'wpcf'),
|
383 |
-
'data-nounce' => wp_create_nonce($id),
|
384 |
-
'data-placeholder' => esc_attr__('Search for a entries', 'wpcf'),
|
385 |
-
'data-post-id' => $post->ID,
|
386 |
-
'data-post-type' => esc_attr($type),
|
387 |
-
'data-input-too-short' => esc_attr(__('Please enter 1 or more character.', 'wpcf')),
|
388 |
-
),
|
389 |
-
);
|
390 |
-
|
391 |
-
if( $belongs_id != 0 && get_post_status( $belongs_id ) ) {
|
392 |
-
//$form[$type]['#attributes']['data-belongs-title'] = get_the_title( $belongs_id );
|
393 |
-
}
|
394 |
-
*/
|
395 |
|
396 |
return $form;
|
397 |
}
|
@@ -637,7 +706,7 @@ function wpcf_pr_admin_wpcf_relationship_check($keys_to_check = array())
|
|
637 |
|
638 |
function wpcf_pr_admin_wpcf_relationship_search()
|
639 |
{
|
640 |
-
wpcf_pr_admin_wpcf_relationship_check(
|
641 |
|
642 |
global $wpdb;
|
643 |
$values_to_prepare = array();
|
@@ -660,7 +729,10 @@ function wpcf_pr_admin_wpcf_relationship_search()
|
|
660 |
|
661 |
$search_where = "";
|
662 |
|
663 |
-
if (
|
|
|
|
|
|
|
664 |
$search_term = "";
|
665 |
if ( method_exists( $wpdb, 'esc_like' ) ) {
|
666 |
$search_term = '%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%';
|
@@ -669,13 +741,16 @@ function wpcf_pr_admin_wpcf_relationship_search()
|
|
669 |
}
|
670 |
$search_where = " AND p.post_title LIKE %s ";
|
671 |
$values_to_prepare[] = $search_term;
|
|
|
|
|
|
|
672 |
}
|
673 |
|
674 |
if (
|
675 |
isset( $_REQUEST['page'] )
|
676 |
&& preg_match( '/^\d+$/', $_REQUEST['page'] )
|
677 |
) {
|
678 |
-
$values_to_prepare[] = (int) $_REQUEST['page'] * $posts_per_page;
|
679 |
} else {
|
680 |
$values_to_prepare[] = 0;
|
681 |
}
|
@@ -689,7 +764,7 @@ function wpcf_pr_admin_wpcf_relationship_search()
|
|
689 |
{$wpml_where}
|
690 |
AND p.post_type = %s
|
691 |
{$search_where}
|
692 |
-
|
693 |
LIMIT %d,%d",
|
694 |
$values_to_prepare
|
695 |
)
|
5 |
*
|
6 |
*/
|
7 |
add_action( 'wpcf_admin_post_init', 'wpcf_pr_admin_post_init_action', 10, 4 );
|
8 |
+
|
9 |
add_action( 'save_post', 'wpcf_pr_admin_save_post_hook', 20, 2 ); // Trigger afer main hook
|
10 |
+
|
11 |
+
/*
|
12 |
+
* Temporary fix for https://core.trac.wordpress.org/ticket/17817
|
13 |
+
*
|
14 |
+
* WordPress 4.7 fixes this issue and the code below is not needed anymore.
|
15 |
+
*
|
16 |
+
* Supported by WPML 3.6.0 and above.
|
17 |
+
*/
|
18 |
+
$wp_version = get_bloginfo( 'version' );
|
19 |
+
if( version_compare( $wp_version, '4.7' ) == -1 ) {
|
20 |
+
|
21 |
+
global $sitepress;
|
22 |
+
$is_wpml_active = (
|
23 |
+
defined( 'ICL_SITEPRESS_VERSION' )
|
24 |
+
&& ! ICL_PLUGIN_INACTIVE
|
25 |
+
&& ! is_null( $sitepress )
|
26 |
+
&& class_exists( 'SitePress' )
|
27 |
+
);
|
28 |
+
|
29 |
+
$is_wpml_required_version = ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.6.0' ) >= 0 );
|
30 |
+
|
31 |
+
if( $is_wpml_active && $is_wpml_required_version ) {
|
32 |
+
// WPML *guarantees* that the wpml_after_save_post action will be fired for each post.
|
33 |
+
remove_action( 'save_post', 'wpcf_pr_admin_save_post_hook', 20 );
|
34 |
+
add_action( 'wpml_after_save_post', 'wpcf_pr_admin_save_post_hook', 10, 2 );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
if ( is_admin() ) {
|
40 |
add_action('wp_ajax_wpcf_relationship_search', 'wpcf_pr_admin_wpcf_relationship_search');
|
41 |
// Deprecated since the introduction of select v.4
|
124 |
}
|
125 |
}
|
126 |
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Determine if a post type can take a part in a post relationship.
|
130 |
+
*
|
131 |
+
* @param string $post_type_slug
|
132 |
+
* @return bool
|
133 |
+
* @since 2.3
|
134 |
+
*/
|
135 |
+
function wpcf_pr_is_post_type_available_for_relationships( $post_type_slug ) {
|
136 |
+
$is_active = ( null != get_post_type_object( $post_type_slug ) );
|
137 |
+
$is_excluded_from_relationships = ( 'attachment' == $post_type_slug );
|
138 |
+
return ( $is_active && ! $is_excluded_from_relationships );
|
139 |
+
}
|
140 |
+
|
141 |
+
|
142 |
/**
|
143 |
* Gets post types that belong to current post type.
|
144 |
*
|
145 |
+
* @param string $parent_post_type_slug
|
146 |
+
* @return array|false
|
147 |
*/
|
148 |
+
function wpcf_pr_admin_get_has( $parent_post_type_slug ) {
|
149 |
static $cache = array();
|
150 |
+
if ( isset( $cache[$parent_post_type_slug] ) ) {
|
151 |
+
return $cache[$parent_post_type_slug];
|
152 |
}
|
153 |
$relationships = get_option( 'wpcf_post_relationship', array() );
|
154 |
+
if ( empty( $relationships[$parent_post_type_slug] ) ) {
|
155 |
return false;
|
156 |
}
|
157 |
// See if enabled
|
158 |
+
foreach ( $relationships[ $parent_post_type_slug ] as $child_post_type_slug => $ignored ) {
|
159 |
+
if ( ! wpcf_pr_is_post_type_available_for_relationships( $child_post_type_slug ) ) {
|
160 |
+
unset( $relationships[ $parent_post_type_slug ][ $child_post_type_slug ] );
|
|
|
161 |
}
|
162 |
}
|
163 |
+
$cache[$parent_post_type_slug] = !empty( $relationships[$parent_post_type_slug] ) ? $relationships[$parent_post_type_slug] : false;
|
164 |
+
return $cache[$parent_post_type_slug];
|
165 |
}
|
166 |
|
167 |
/**
|
168 |
* Gets post types that current post type belongs to.
|
169 |
*
|
170 |
+
* @param string $post_type
|
171 |
+
* @return array|false
|
172 |
*/
|
173 |
function wpcf_pr_admin_get_belongs( $post_type ) {
|
174 |
static $cache = array();
|
179 |
$results = array();
|
180 |
if ( is_array( $relationships ) ) {
|
181 |
foreach ( $relationships as $has => $belongs ) {
|
182 |
+
|
183 |
+
if ( ! wpcf_pr_is_post_type_available_for_relationships( $has ) ) {
|
|
|
184 |
continue;
|
185 |
}
|
186 |
+
|
187 |
if ( array_key_exists( $post_type, $belongs ) ) {
|
188 |
$results[$has] = $belongs[$post_type];
|
189 |
}
|
390 |
$id = esc_attr(sprintf('wpcf_pr_belongs_%d_%s', $post->ID, $type));
|
391 |
$belongs_id = isset( $belongs['belongs'][$type] ) ? $belongs['belongs'][$type] : 0;
|
392 |
|
393 |
+
$options_array = array();
|
394 |
|
395 |
+
$values_to_prepare = array();
|
396 |
+
|
397 |
+
$post_status = array( 'publish', 'private' );
|
398 |
+
|
399 |
+
$wpml_join = $wpml_where = "";
|
400 |
+
$is_translated_post_type = apply_filters( 'wpml_is_translated_post_type', false, $type );
|
401 |
+
|
402 |
+
if ( $is_translated_post_type ) {
|
403 |
+
$wpml_current_language = apply_filters( 'wpml_current_language', '' );
|
404 |
+
$wpml_join = " JOIN {$wpdb->prefix}icl_translations t ";
|
405 |
+
$wpml_where = " AND p.ID = t.element_id AND t.language_code = %s ";
|
406 |
+
$values_to_prepare[] = $wpml_current_language;
|
407 |
+
}
|
408 |
+
|
409 |
+
$values_to_prepare[] = sanitize_text_field( $type );
|
410 |
+
|
411 |
+
$not_in_selected = '';
|
412 |
if ( $belongs_id ) {
|
413 |
+
$not_in_selected = ' AND p.ID != %d';
|
414 |
+
$values_to_prepare[] = (int) $belongs_id;
|
415 |
$options_array[ $belongs_id ] = array(
|
416 |
'#title' => get_the_title( $belongs_id ),
|
417 |
'#value' => $belongs_id,
|
418 |
);
|
419 |
+
} else {
|
420 |
+
$options_array[ '' ] = array(
|
421 |
+
'#title' => '',
|
422 |
+
'#value' => '',
|
423 |
+
);
|
424 |
+
}
|
425 |
+
|
426 |
+
$parents_available = $wpdb->get_results(
|
427 |
+
$wpdb->prepare(
|
428 |
+
"SELECT p.ID, p.post_title
|
429 |
+
FROM {$wpdb->posts} p {$wpml_join}
|
430 |
+
WHERE p.post_status IN ('" . implode( "','" , $post_status ) . "')
|
431 |
+
{$wpml_where}
|
432 |
+
AND p.post_type = %s
|
433 |
+
{$not_in_selected}
|
434 |
+
ORDER BY p.post_date DESC
|
435 |
+
LIMIT 15",
|
436 |
+
$values_to_prepare
|
437 |
+
)
|
438 |
+
);
|
439 |
+
|
440 |
+
foreach ( $parents_available as $parent_option ) {
|
441 |
+
$options_array[ $parent_option->ID ] = array(
|
442 |
+
'#title' => $parent_option->post_title,
|
443 |
+
'#value' => $parent_option->ID,
|
444 |
+
);
|
445 |
}
|
446 |
|
447 |
+
|
448 |
$form[$type] = array(
|
449 |
'#type' => 'select',
|
450 |
'#name' => 'wpcf_pr_belongs[' . $post->ID . '][' . $type . ']',
|
458 |
'data-placeholder' => esc_attr( sprintf( __('Search for %s', 'wpcf'), $temp_type->labels->name ) ),
|
459 |
'data-post-id' => $post->ID,
|
460 |
'data-post-type' => esc_attr($type),
|
461 |
+
'autocomplete' => 'off'
|
462 |
),
|
463 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
464 |
|
465 |
return $form;
|
466 |
}
|
706 |
|
707 |
function wpcf_pr_admin_wpcf_relationship_search()
|
708 |
{
|
709 |
+
wpcf_pr_admin_wpcf_relationship_check();
|
710 |
|
711 |
global $wpdb;
|
712 |
$values_to_prepare = array();
|
729 |
|
730 |
$search_where = "";
|
731 |
|
732 |
+
if (
|
733 |
+
isset( $_REQUEST['s'] )
|
734 |
+
&& $_REQUEST['s'] != ''
|
735 |
+
) {
|
736 |
$search_term = "";
|
737 |
if ( method_exists( $wpdb, 'esc_like' ) ) {
|
738 |
$search_term = '%' . $wpdb->esc_like( $_REQUEST['s'] ) . '%';
|
741 |
}
|
742 |
$search_where = " AND p.post_title LIKE %s ";
|
743 |
$values_to_prepare[] = $search_term;
|
744 |
+
$orderby = ' ORDER BY p.post_title ';
|
745 |
+
} else {
|
746 |
+
$orderby = ' ORDER BY p.post_date DESC ';
|
747 |
}
|
748 |
|
749 |
if (
|
750 |
isset( $_REQUEST['page'] )
|
751 |
&& preg_match( '/^\d+$/', $_REQUEST['page'] )
|
752 |
) {
|
753 |
+
$values_to_prepare[] = ( (int) $_REQUEST['page'] - 1 ) * $posts_per_page;
|
754 |
} else {
|
755 |
$values_to_prepare[] = 0;
|
756 |
}
|
764 |
{$wpml_where}
|
765 |
AND p.post_type = %s
|
766 |
{$search_where}
|
767 |
+
{$orderby}
|
768 |
LIMIT %d,%d",
|
769 |
$values_to_prepare
|
770 |
)
|
library/toolset/types/embedded/includes/usermeta-post.php
CHANGED
@@ -66,6 +66,9 @@ function wpcf_admin_userprofile_init($user_id){
|
|
66 |
|
67 |
// Process fields
|
68 |
if ( empty($profile_only_preview) ){
|
|
|
|
|
|
|
69 |
if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
|
70 |
$errors = get_user_meta( $user_id->ID, '__wpcf-invalid-fields',
|
71 |
true );
|
@@ -76,11 +79,10 @@ function wpcf_admin_userprofile_init($user_id){
|
|
76 |
|
77 |
$output = '<div class="wpcf-group-area wpcf-group-area_'
|
78 |
. $group['slug'] . '">' . "\n\n" . '<h3>'
|
79 |
-
.
|
80 |
-
$group['name'] ) . '</h3>' . "\n\n";
|
81 |
|
82 |
if ( !empty( $group['description'] ) ) {
|
83 |
-
$output .= '<span>' . wpautop(
|
84 |
. '</span>' . "\n\n";
|
85 |
}
|
86 |
|
@@ -197,8 +199,10 @@ function wpcf_usermeta_preview_profile( $user_id, $group, $echo = ''){
|
|
197 |
global $wpcf;
|
198 |
//print_r($group);exit;
|
199 |
$fields = $group['fields'];
|
|
|
|
|
200 |
$group_output = '<div class="wpcf-group-area wpcf-group-area-' . $group['slug'] . '">' . "\n\n";
|
201 |
-
$group_output .= '<h3 class="wpcf-group-header-'. $group['slug'] .'">'.
|
202 |
|
203 |
|
204 |
foreach ( $fields as $field ) {
|
@@ -582,14 +586,15 @@ function wpcf_admin_userprofilesave_init($user_id){
|
|
582 |
function wpcf_admin_render_fields( $group, $user_id, $echo = '') {
|
583 |
|
584 |
global $wpcf;
|
|
|
|
|
585 |
$output = '<div class="wpcf-group-area wpcf-group-area_' . $group['slug'] . '">' . "\n\n";
|
586 |
-
$output .= '<h3>'.
|
587 |
if ( !empty( $group['fields'] ) ) {
|
588 |
// Display description
|
589 |
if ( !empty( $group['description'] ) ) {
|
590 |
$output .= '<span>'
|
591 |
-
. wpautop(
|
592 |
-
$group['description'] ) ) . '</span>' . "\n\n";
|
593 |
}
|
594 |
|
595 |
$output .= '<div class="wpcf-profile-field-line">' . "\n\n";
|
66 |
|
67 |
// Process fields
|
68 |
if ( empty($profile_only_preview) ){
|
69 |
+
|
70 |
+
$group_wpml = new Types_Wpml_Field_Group( Types_Field_Group_User_Factory::load( $group['slug'] ) );
|
71 |
+
|
72 |
if ( defined( 'WPTOOLSET_FORMS_VERSION' ) ) {
|
73 |
$errors = get_user_meta( $user_id->ID, '__wpcf-invalid-fields',
|
74 |
true );
|
79 |
|
80 |
$output = '<div class="wpcf-group-area wpcf-group-area_'
|
81 |
. $group['slug'] . '">' . "\n\n" . '<h3>'
|
82 |
+
. $group_wpml->translate_name() . '</h3>' . "\n\n";
|
|
|
83 |
|
84 |
if ( !empty( $group['description'] ) ) {
|
85 |
+
$output .= '<span>' . wpautop( $group_wpml->translate_description() )
|
86 |
. '</span>' . "\n\n";
|
87 |
}
|
88 |
|
199 |
global $wpcf;
|
200 |
//print_r($group);exit;
|
201 |
$fields = $group['fields'];
|
202 |
+
$group_wpml = new Types_Wpml_Field_Group( Types_Field_Group_User_Factory::load( $group['slug'] ) );
|
203 |
+
|
204 |
$group_output = '<div class="wpcf-group-area wpcf-group-area-' . $group['slug'] . '">' . "\n\n";
|
205 |
+
$group_output .= '<h3 class="wpcf-group-header-'. $group['slug'] .'">'. $group_wpml->translate_name() .'</h3>'. "\n\n";
|
206 |
|
207 |
|
208 |
foreach ( $fields as $field ) {
|
586 |
function wpcf_admin_render_fields( $group, $user_id, $echo = '') {
|
587 |
|
588 |
global $wpcf;
|
589 |
+
$group_wpml = new Types_Wpml_Field_Group( Types_Field_Group_User_Factory::load( $group['slug'] ) );
|
590 |
+
|
591 |
$output = '<div class="wpcf-group-area wpcf-group-area_' . $group['slug'] . '">' . "\n\n";
|
592 |
+
$output .= '<h3>'. $group_wpml->translate_name() .'</h3>' . "\n\n";
|
593 |
if ( !empty( $group['fields'] ) ) {
|
594 |
// Display description
|
595 |
if ( !empty( $group['description'] ) ) {
|
596 |
$output .= '<span>'
|
597 |
+
. wpautop( $group_wpml->translate_description() ) . '</span>' . "\n\n";
|
|
|
598 |
}
|
599 |
|
600 |
$output .= '<div class="wpcf-profile-field-line">' . "\n\n";
|
library/toolset/types/embedded/includes/wpml.php
CHANGED
@@ -183,7 +183,7 @@ function wpcf_translate_register_string( $context, $name, $value,
|
|
183 |
$allow_empty_value = false ) {
|
184 |
if ( function_exists( 'icl_register_string' ) ) {
|
185 |
icl_register_string( $context, $name, stripslashes( $value ),
|
186 |
-
|
187 |
}
|
188 |
}
|
189 |
|
@@ -300,13 +300,8 @@ function wpcf_admin_bulk_string_translation() {
|
|
300 |
// Register groups
|
301 |
$groups = wpcf_admin_fields_get_groups();
|
302 |
foreach ( $groups as $group_id => $group ) {
|
303 |
-
|
304 |
-
|
305 |
-
'group ' . $group_id . ' name', $group['name'] );
|
306 |
-
if ( isset( $group['description'] ) ) {
|
307 |
-
wpcf_translate_register_string( 'plugin Types',
|
308 |
-
'group ' . $group_id . ' description', $group['description'] );
|
309 |
-
}
|
310 |
}
|
311 |
|
312 |
// Register fields
|
@@ -1236,7 +1231,7 @@ function wpcf_wpml_warnings_init()
|
|
1236 |
*/
|
1237 |
function wpcf_wpml_warning()
|
1238 |
{
|
1239 |
-
if(!defined('WPML_ST_PATH') || !class_exists( 'ICL_AdminNotifier' )) return;
|
1240 |
ICL_AdminNotifier::displayMessages('wp-types');
|
1241 |
}
|
1242 |
|
183 |
$allow_empty_value = false ) {
|
184 |
if ( function_exists( 'icl_register_string' ) ) {
|
185 |
icl_register_string( $context, $name, stripslashes( $value ),
|
186 |
+
$allow_empty_value );
|
187 |
}
|
188 |
}
|
189 |
|
300 |
// Register groups
|
301 |
$groups = wpcf_admin_fields_get_groups();
|
302 |
foreach ( $groups as $group_id => $group ) {
|
303 |
+
$group_wpml = new Types_Wpml_Field_Group( Types_Field_Group_Post_Factory::load( $group['slug'] ) );
|
304 |
+
$group_wpml->register();
|
|
|
|
|
|
|
|
|
|
|
305 |
}
|
306 |
|
307 |
// Register fields
|
1231 |
*/
|
1232 |
function wpcf_wpml_warning()
|
1233 |
{
|
1234 |
+
if(!defined('ICL_SITEPRESS_VERSION') || !defined('WPML_ST_PATH') || !class_exists( 'ICL_AdminNotifier' )) return;
|
1235 |
ICL_AdminNotifier::displayMessages('wp-types');
|
1236 |
}
|
1237 |
|
library/toolset/types/embedded/resources/css/basic.css
CHANGED
@@ -1450,4 +1450,9 @@ input#slug+p.wpcf-form-description {
|
|
1450 |
}
|
1451 |
.ui-sortable-handle .description{
|
1452 |
font-weight: normal;
|
|
|
|
|
|
|
|
|
|
|
1453 |
}
|
1450 |
}
|
1451 |
.ui-sortable-handle .description{
|
1452 |
font-weight: normal;
|
1453 |
+
}
|
1454 |
+
|
1455 |
+
/* todo move to common */
|
1456 |
+
.ui-datepicker {
|
1457 |
+
z-index: 10000 !important;
|
1458 |
}
|
library/toolset/types/embedded/resources/js/post-relationship.js
CHANGED
@@ -1021,94 +1021,113 @@ function wpcfBindSelect2($) {
|
|
1021 |
}
|
1022 |
|
1023 |
function wpcfBindSelect2For( element ) {
|
1024 |
-
var $ = jQuery
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
data: function (params) {
|
1033 |
-
return {
|
1034 |
-
s: params.term,
|
1035 |
-
page: params.page,
|
1036 |
-
post_id: element.data('post-id'),
|
1037 |
-
post_type: element.data('post-type')
|
1038 |
-
};
|
1039 |
-
},
|
1040 |
-
processResults: function (data, params) {
|
1041 |
-
params.page = params.page || 1;
|
1042 |
-
return {
|
1043 |
-
results: data.items,
|
1044 |
-
pagination: {
|
1045 |
-
more: ( params.page * wpcf_post_relationship_messages.parent_per_page ) < data.total_count
|
1046 |
-
}
|
1047 |
-
};
|
1048 |
-
},
|
1049 |
-
cache: false
|
1050 |
-
},
|
1051 |
-
escapeMarkup: function (markup) { return markup; },
|
1052 |
-
minimumInputLength: 2,
|
1053 |
-
triggerChange: true,
|
1054 |
-
})
|
1055 |
-
.on('toolset_select2:select', function( evt ) {
|
1056 |
-
$.ajax({
|
1057 |
-
url: ajaxurl,
|
1058 |
-
dataType: "json",
|
1059 |
-
data: {
|
1060 |
-
action: 'wpcf_relationship_update',
|
1061 |
-
nounce: element.data('nounce'),
|
1062 |
-
post_id: element.data('post-id'),
|
1063 |
-
post_type: element.data('post-type'),
|
1064 |
-
p: element.val()
|
1065 |
-
},
|
1066 |
-
success: function( response ) {
|
1067 |
-
var parent_edit_button = element
|
1068 |
-
.closest( '.form-item' )
|
1069 |
-
.find( '.js-wpcf-pr-parent-edit' );
|
1070 |
-
parent_edit_button
|
1071 |
-
.removeClass( 'disabled' )
|
1072 |
-
.fadeIn( 'fast' )
|
1073 |
-
.addClass( 'wpcf-saved' )
|
1074 |
-
.attr( 'href', response.data.edit_link + '?post=' + element.val() + '&action=edit' );
|
1075 |
-
setTimeout( function() {
|
1076 |
-
parent_edit_button.removeClass( 'wpcf-saved' );
|
1077 |
-
},
|
1078 |
-
1000
|
1079 |
-
);
|
1080 |
-
}
|
1081 |
});
|
1082 |
-
}
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1093 |
},
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
parent_edit_button.removeClass( 'wpcf-deleted' );
|
1105 |
-
});
|
1106 |
-
},
|
1107 |
-
1000
|
1108 |
-
);
|
1109 |
}
|
1110 |
});
|
1111 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1112 |
}
|
1113 |
jQuery(document).ready(function($) {
|
1114 |
wpcfBindSelect2($);
|
1021 |
}
|
1022 |
|
1023 |
function wpcfBindSelect2For( element ) {
|
1024 |
+
var $ = jQuery,
|
1025 |
+
options = element.find( 'option' ),
|
1026 |
+
element_s2_instance;
|
1027 |
+
|
1028 |
+
if ( options.length < 16 ) {
|
1029 |
+
element_s2_instance = element.toolset_select2({
|
1030 |
+
allowClear: true,
|
1031 |
+
triggerChange: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1032 |
});
|
1033 |
+
} else {
|
1034 |
+
element_s2_instance = element.toolset_select2({
|
1035 |
+
allowClear: true,
|
1036 |
+
ajax: {
|
1037 |
+
url: ajaxurl + '?action=wpcf_relationship_search&nounce='+element.data('nounce'),
|
1038 |
+
dataType: 'json',
|
1039 |
+
delay: 250,
|
1040 |
+
type: 'post',
|
1041 |
+
data: function (params) {
|
1042 |
+
return {
|
1043 |
+
s: params.term,
|
1044 |
+
page: params.page,
|
1045 |
+
post_id: element.data('post-id'),
|
1046 |
+
post_type: element.data('post-type')
|
1047 |
+
};
|
1048 |
+
},
|
1049 |
+
processResults: function (data, params) {
|
1050 |
+
params.page = params.page || 1;
|
1051 |
+
return {
|
1052 |
+
results: data.items,
|
1053 |
+
pagination: {
|
1054 |
+
more: ( params.page * wpcf_post_relationship_messages.parent_per_page ) < data.total_count
|
1055 |
+
}
|
1056 |
+
};
|
1057 |
+
},
|
1058 |
+
cache: false
|
1059 |
},
|
1060 |
+
escapeMarkup: function (markup) { return markup; },
|
1061 |
+
//minimumInputLength: 2,// No minimum input length so we can search by empty terms, hece offer latests parents
|
1062 |
+
triggerChange: true,
|
1063 |
+
defaultResults: function() {
|
1064 |
+
var results = {};
|
1065 |
+
results.items = [],
|
1066 |
+
$.each( options, function( index, option ) {
|
1067 |
+
results.items.push( { id: option.value, text: option.text } );
|
1068 |
+
});
|
1069 |
+
return results;
|
|
|
|
|
|
|
|
|
|
|
1070 |
}
|
1071 |
});
|
1072 |
+
}
|
1073 |
+
element_s2_instance
|
1074 |
+
.on('toolset_select2:select', function( evt ) {
|
1075 |
+
$.ajax({
|
1076 |
+
url: ajaxurl,
|
1077 |
+
dataType: "json",
|
1078 |
+
data: {
|
1079 |
+
action: 'wpcf_relationship_update',
|
1080 |
+
nounce: element.data('nounce'),
|
1081 |
+
post_id: element.data('post-id'),
|
1082 |
+
post_type: element.data('post-type'),
|
1083 |
+
p: element.val()
|
1084 |
+
},
|
1085 |
+
success: function( response ) {
|
1086 |
+
var parent_edit_button = element
|
1087 |
+
.closest( '.form-item' )
|
1088 |
+
.find( '.js-wpcf-pr-parent-edit' );
|
1089 |
+
parent_edit_button
|
1090 |
+
.removeClass( 'disabled' )
|
1091 |
+
.fadeIn( 'fast' )
|
1092 |
+
.addClass( 'wpcf-saved' )
|
1093 |
+
.attr( 'href', response.data.edit_link + '?post=' + element.val() + '&action=edit' );
|
1094 |
+
setTimeout( function() {
|
1095 |
+
parent_edit_button.removeClass( 'wpcf-saved' );
|
1096 |
+
},
|
1097 |
+
1000
|
1098 |
+
);
|
1099 |
+
}
|
1100 |
+
});
|
1101 |
+
})
|
1102 |
+
.on('toolset_select2:unselect', function( evt ) {
|
1103 |
+
$.ajax({
|
1104 |
+
url: ajaxurl,
|
1105 |
+
dataType: "json",
|
1106 |
+
data: {
|
1107 |
+
action: 'wpcf_relationship_update',
|
1108 |
+
nounce: element.data('nounce'),
|
1109 |
+
post_id: element.data('post-id'),
|
1110 |
+
post_type: element.data('post-type'),
|
1111 |
+
p: 0
|
1112 |
+
},
|
1113 |
+
success: function() {
|
1114 |
+
var parent_edit_button = element
|
1115 |
+
.closest( '.form-item' )
|
1116 |
+
.find( '.js-wpcf-pr-parent-edit' );
|
1117 |
+
parent_edit_button
|
1118 |
+
.addClass( 'disabled wpcf-deleted' )
|
1119 |
+
.attr( 'href', '#');
|
1120 |
+
setTimeout( function() {
|
1121 |
+
parent_edit_button
|
1122 |
+
.fadeOut( 500, function() {
|
1123 |
+
parent_edit_button.removeClass( 'wpcf-deleted' );
|
1124 |
+
});
|
1125 |
+
},
|
1126 |
+
1000
|
1127 |
+
);
|
1128 |
+
}
|
1129 |
+
});
|
1130 |
+
});
|
1131 |
}
|
1132 |
jQuery(document).ready(function($) {
|
1133 |
wpcfBindSelect2($);
|
library/toolset/types/embedded/usermeta-init.php
CHANGED
@@ -345,155 +345,17 @@ function wpcf_admin_post_add_usermeta_to_editor_js( $menu, $views_callback = fal
|
|
345 |
/**
|
346 |
* Calls view function for specific field type.
|
347 |
*
|
348 |
-
* @
|
|
|
|
|
|
|
349 |
*
|
350 |
-
* @
|
351 |
-
* @param type $atts
|
352 |
-
* @return type
|
353 |
*
|
354 |
-
* @deprecated
|
355 |
*/
|
356 |
-
function types_render_usermeta_field( $field_id, $params, $content = null,
|
357 |
-
|
358 |
-
|
359 |
-
require_once WPCF_EMBEDDED_INC_ABSPATH . '/fields.php';
|
360 |
-
global $wpcf, $post, $wpdb;
|
361 |
-
|
362 |
-
// HTML var holds actual output
|
363 |
-
$html = '';
|
364 |
-
|
365 |
-
// Set post ID
|
366 |
-
$post_id = $post->ID;
|
367 |
-
if ( isset( $params['post_id'] ) && !empty( $params['post_id'] ) ) {
|
368 |
-
$post_id = $params['post_id'];
|
369 |
-
}
|
370 |
-
|
371 |
-
// Get field
|
372 |
-
$field = wpcf_fields_get_field_by_slug( $field_id, 'wpcf-usermeta' );
|
373 |
-
|
374 |
-
// If field not found return empty string
|
375 |
-
if ( empty( $field ) ) {
|
376 |
-
|
377 |
-
// Log
|
378 |
-
if ( !function_exists( 'wplogger' ) ) {
|
379 |
-
require_once WPCF_EMBEDDED_TOOLSET_ABSPATH . '/toolset-common/wplogger.php';
|
380 |
-
}
|
381 |
-
global $wplogger;
|
382 |
-
$wplogger->log( 'types_render_usermeta_field call for missing field \''
|
383 |
-
. $field_id . '\'', WPLOG_DEBUG );
|
384 |
-
|
385 |
-
return '';
|
386 |
-
}
|
387 |
-
|
388 |
-
//Get user By ID
|
389 |
-
if ( isset( $params['user_id'] ) ) {
|
390 |
-
$user_id = $params['user_id'];
|
391 |
-
} else if ( isset( $params['user_name'] ) ) { //Get user by login
|
392 |
-
$user_id = $wpdb->get_var(
|
393 |
-
$wpdb->prepare(
|
394 |
-
"SELECT * FROM " . $wpdb->users . " WHERE user_login = %s",
|
395 |
-
$params['user_name']
|
396 |
-
)
|
397 |
-
);
|
398 |
-
} else if ( isset( $params['user_is_author'] ) ) { //Get Post author
|
399 |
-
$user_id = $post->post_author;
|
400 |
-
} else if ( isset( $params['user_current'] ) ) {//Get current logged user
|
401 |
-
$user_id = wpcf_usermeta_get_user();
|
402 |
-
} else { //If empty get post author, if no post, return empty
|
403 |
-
if ( !empty( $post_id ) ) {
|
404 |
-
$user_id = $post->post_author;
|
405 |
-
} else {
|
406 |
-
return;
|
407 |
-
}
|
408 |
-
}
|
409 |
-
|
410 |
-
if ( empty( $user_id ) ) {
|
411 |
-
return;
|
412 |
-
}
|
413 |
-
|
414 |
-
// Set field
|
415 |
-
$wpcf->usermeta_field->set( $user_id, $field );
|
416 |
-
|
417 |
-
// See if repetitive
|
418 |
-
if ( wpcf_admin_is_repetitive( $field ) ) {
|
419 |
-
$wpcf->usermeta_repeater->set( $user_id, $field );
|
420 |
-
$_meta = $wpcf->usermeta_repeater->_get_meta();
|
421 |
-
$meta = $_meta['custom_order'];
|
422 |
-
// $meta = get_post_meta( $post_id,
|
423 |
-
// wpcf_types_get_meta_prefix( $field ) . $field['slug'], false );
|
424 |
-
// Sometimes if meta is empty - array(0 => '') is returned
|
425 |
-
if ( (count( $meta ) == 1 ) ) {
|
426 |
-
$meta_id = key( $meta );
|
427 |
-
$_temp = array_shift( $meta );
|
428 |
-
if ( strval( $_temp ) == '' ) {
|
429 |
-
return '';
|
430 |
-
} else {
|
431 |
-
|
432 |
-
$params['field_value'] = $_temp;
|
433 |
-
return types_render_field_single( $field, $params, $content,
|
434 |
-
$code, $meta_id );
|
435 |
-
}
|
436 |
-
} else if ( !empty( $meta ) ) {
|
437 |
-
$output = '';
|
438 |
-
|
439 |
-
if ( isset( $params['index'] ) ) {
|
440 |
-
$index = $params['index'];
|
441 |
-
} else {
|
442 |
-
$index = '';
|
443 |
-
}
|
444 |
-
|
445 |
-
// Allow wpv-for-each shortcode to set the index
|
446 |
-
$index = apply_filters( 'wpv-for-each-index', $index );
|
447 |
-
|
448 |
-
if ( $index === '' ) {
|
449 |
-
$output = array();
|
450 |
-
foreach ( $meta as $temp_key => $temp_value ) {
|
451 |
-
$params['field_value'] = $temp_value;
|
452 |
-
$temp_output = types_render_field_single( $field, $params,
|
453 |
-
$content, $code, $temp_key );
|
454 |
-
if ( !empty( $temp_output ) ) {
|
455 |
-
$output[] = $temp_output;
|
456 |
-
}
|
457 |
-
}
|
458 |
-
if ( !empty( $output ) && isset( $params['separator'] ) ) {
|
459 |
-
$output = implode( html_entity_decode( $params['separator'] ),
|
460 |
-
$output );
|
461 |
-
} else if ( !empty( $output ) ) {
|
462 |
-
$output = implode( '', $output );
|
463 |
-
} else {
|
464 |
-
return '';
|
465 |
-
}
|
466 |
-
} else {
|
467 |
-
// Make sure indexed right
|
468 |
-
$_index = 0;
|
469 |
-
foreach ( $meta as $temp_key => $temp_value ) {
|
470 |
-
if ( $_index == $index ) {
|
471 |
-
$params['field_value'] = $temp_value;
|
472 |
-
return types_render_field_single( $field, $params,
|
473 |
-
$content, $code, $temp_key );
|
474 |
-
}
|
475 |
-
$_index++;
|
476 |
-
}
|
477 |
-
// If missed index
|
478 |
-
return '';
|
479 |
-
}
|
480 |
-
$html = $output;
|
481 |
-
} else {
|
482 |
-
return '';
|
483 |
-
}
|
484 |
-
} else {
|
485 |
-
$params['field_value'] = get_user_meta( $user_id,
|
486 |
-
wpcf_types_get_meta_prefix( $field ) . $field['slug'], true );
|
487 |
-
if ( $params['field_value'] == '' && $field['type'] != 'checkbox' ) {
|
488 |
-
return '';
|
489 |
-
}
|
490 |
-
$html = types_render_field_single( $field, $params, $content, $code,
|
491 |
-
$wpcf->usermeta_field->meta_object->umeta_id );
|
492 |
-
}
|
493 |
-
|
494 |
-
// API filter
|
495 |
-
// $wpcf->usermeta_field->set( $user_id, $field );
|
496 |
-
return $wpcf->usermeta_field->html( $html, $params );
|
497 |
}
|
498 |
|
499 |
/**
|
345 |
/**
|
346 |
* Calls view function for specific field type.
|
347 |
*
|
348 |
+
* @param $field_id
|
349 |
+
* @param $params
|
350 |
+
* @param null $content
|
351 |
+
* @param string $code
|
352 |
*
|
353 |
+
* @return string
|
|
|
|
|
354 |
*
|
355 |
+
* @deprecated Use types_render_usermeta() instead.
|
356 |
*/
|
357 |
+
function types_render_usermeta_field( $field_id, $params, $content = null, $code = '' ) {
|
358 |
+
return types_render_usermeta( $field_id, $params, $content, $code );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
}
|
360 |
|
361 |
/**
|
library/toolset/types/includes/fields.php
CHANGED
@@ -246,6 +246,8 @@ function wpcf_admin_fields_save_group( $group, $post_type = TYPES_CUSTOM_FIELD_G
|
|
246 |
}
|
247 |
|
248 |
$update = false;
|
|
|
|
|
249 |
if ( isset( $group['id'] ) && !empty($group['id']) ) {
|
250 |
$update = true;
|
251 |
$post_to_update = get_post( $group['id'] );
|
@@ -253,6 +255,7 @@ function wpcf_admin_fields_save_group( $group, $post_type = TYPES_CUSTOM_FIELD_G
|
|
253 |
return false;
|
254 |
}
|
255 |
$post['ID'] = $post_to_update->ID;
|
|
|
256 |
$post['post_status'] = $post_to_update->post_status;
|
257 |
}
|
258 |
|
@@ -281,10 +284,21 @@ function wpcf_admin_fields_save_group( $group, $post_type = TYPES_CUSTOM_FIELD_G
|
|
281 |
|
282 |
// WPML register strings
|
283 |
if ( function_exists( 'icl_register_string' ) ) {
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
}
|
289 |
|
290 |
// admin message
|
246 |
}
|
247 |
|
248 |
$update = false;
|
249 |
+
$slug_pre_save = false;
|
250 |
+
|
251 |
if ( isset( $group['id'] ) && !empty($group['id']) ) {
|
252 |
$update = true;
|
253 |
$post_to_update = get_post( $group['id'] );
|
255 |
return false;
|
256 |
}
|
257 |
$post['ID'] = $post_to_update->ID;
|
258 |
+
$slug_pre_save = $post_to_update->post_name;
|
259 |
$post['post_status'] = $post_to_update->post_status;
|
260 |
}
|
261 |
|
284 |
|
285 |
// WPML register strings
|
286 |
if ( function_exists( 'icl_register_string' ) ) {
|
287 |
+
|
288 |
+
try {
|
289 |
+
// Legacy function gives us only the underlying post type of the field group.
|
290 |
+
$group_factory = Types_Field_Utils::get_group_factory_by_post_type( $post_type );
|
291 |
+
$field_group = $group_factory->load_field_group( sanitize_title( $group['name'] ) );
|
292 |
+
|
293 |
+
// Skip registering if the group does not exist.
|
294 |
+
if( null != $field_group ) {
|
295 |
+
$group_wpml = new Types_Wpml_Field_Group( $field_group );
|
296 |
+
$group_wpml->register( $slug_pre_save );
|
297 |
+
}
|
298 |
+
|
299 |
+
} catch( InvalidArgumentException $e ) {
|
300 |
+
// Something is seriously wrong - there's no field group factory for given post type, bail.
|
301 |
+
}
|
302 |
}
|
303 |
|
304 |
// admin message
|
library/toolset/types/includes/post-relationship.php
CHANGED
@@ -331,32 +331,47 @@ function wpcf_admin_metabox_relationship($post_type)
|
|
331 |
)
|
332 |
)
|
333 |
);
|
334 |
-
|
335 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
$form['alert'] = array(
|
337 |
'#type' => 'notice',
|
338 |
-
'#markup' =>
|
339 |
);
|
340 |
-
$form = wpcf_form(__FUNCTION__, $form);
|
341 |
echo $form->renderForm();
|
342 |
-
return
|
343 |
}
|
344 |
|
345 |
-
$post_type = false;;
|
346 |
-
|
347 |
$post_type = $custom_types[$_REQUEST['wpcf-post-type']];
|
|
|
348 |
unset($custom_types);
|
349 |
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
$has = wpcf_pr_admin_get_has( $post_type['slug'] );
|
354 |
$belongs = wpcf_pr_admin_get_belongs( $post_type['slug'] );
|
355 |
$post_types = get_post_types( '', 'objects' );
|
356 |
|
357 |
-
|
358 |
-
* parents
|
359 |
-
*/
|
360 |
$form['parent-h3'] = array(
|
361 |
'#type' => 'markup',
|
362 |
'#markup' => sprintf(
|
@@ -374,40 +389,40 @@ function wpcf_admin_metabox_relationship($post_type)
|
|
374 |
);
|
375 |
$options = array();
|
376 |
|
377 |
-
|
378 |
-
* build excluded post types
|
379 |
-
*/
|
380 |
global $wpcf;
|
381 |
$excluded_post_types = $wpcf->excluded_post_types;
|
382 |
$excluded_post_types[] = $post_type['slug'];
|
|
|
|
|
|
|
383 |
|
384 |
-
foreach ( $post_types as $
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
)
|
391 |
-
) {
|
392 |
continue;
|
393 |
}
|
394 |
-
|
395 |
-
|
396 |
-
'#
|
397 |
-
'#
|
|
|
398 |
'#inline' => true,
|
399 |
'#before' => '<li>',
|
400 |
'#after' => '</li>',
|
401 |
'#attributes' => array(
|
402 |
'class' => 'js-wpcf-relationship-checkbox',
|
403 |
'data-wpcf-type' => 'belongs',
|
404 |
-
'data-wpcf-value' => esc_attr($
|
405 |
'data-wpcf-message-disabled' => esc_attr__('This post type is disabled, becouse is used as child post.', 'wpcf'),
|
406 |
),
|
407 |
);
|
408 |
-
if ( isset( $has[$
|
409 |
-
$options[$
|
410 |
-
$options[$
|
411 |
}
|
412 |
}
|
413 |
$form['table-pr-belongs-form'] = array(
|
@@ -419,9 +434,8 @@ function wpcf_admin_metabox_relationship($post_type)
|
|
419 |
'#after' => '</ul>',
|
420 |
);
|
421 |
|
422 |
-
|
423 |
-
|
424 |
-
*/
|
425 |
$form['child-h3'] = array(
|
426 |
'#type' => 'markup',
|
427 |
'#markup' => sprintf(
|
@@ -438,11 +452,11 @@ function wpcf_admin_metabox_relationship($post_type)
|
|
438 |
)
|
439 |
);
|
440 |
$options = array();
|
441 |
-
foreach ( $post_types as $
|
442 |
if (
|
443 |
-
in_array( $
|
444 |
|| (
|
445 |
-
!$
|
446 |
&& !apply_filters('wpcf_show_ui_hide_in_relationships', true)
|
447 |
)
|
448 |
) {
|
@@ -452,46 +466,46 @@ function wpcf_admin_metabox_relationship($post_type)
|
|
452 |
$nonce = sprintf(
|
453 |
'child-post-fields-%s-%s',
|
454 |
$post_type['slug'],
|
455 |
-
$
|
456 |
);
|
457 |
$a = sprintf(
|
458 |
' <span>(<a class="js-wpcf-edit-child-post-fields" href="#" data-wpcf-nonce="%s" data-wpcf-child="%s" data-wpcf-parent="%s" data-wpcf-title="%s" data-wpcf-buttons-apply="%s" data-wpcf-buttons-cancel="%s" data-wpcf-message-loading="%s" data-wpcf-save-status="%s">%s</a>)</span>',
|
459 |
esc_attr(wp_create_nonce($nonce)),
|
460 |
-
esc_attr($
|
461 |
esc_attr($post_type['slug']),
|
462 |
esc_attr(
|
463 |
sprintf(
|
464 |
__('Select child fields from %s to be displayed in Post Relationship table', 'wpcf'),
|
465 |
-
$
|
466 |
)
|
467 |
),
|
468 |
esc_attr__('Apply', 'wpcf'),
|
469 |
esc_attr__('Cancel', 'wpcf'),
|
470 |
esc_attr__('Please Wait, Loading…', 'wpcf'),
|
471 |
-
esc_attr(isset( $has[$
|
472 |
esc_attr__('Select fields', 'wpcf')
|
473 |
);
|
474 |
|
475 |
-
$options[$
|
476 |
-
'#name' => 'ct[post_relationship][has][' . $
|
477 |
-
'#title' => $
|
478 |
'#inline' => true,
|
479 |
'#before' => '<li>',
|
480 |
'#after' => $a.'</li>',
|
481 |
'#attributes' => array(
|
482 |
'class' => 'js-wpcf-relationship-checkbox',
|
483 |
'data-wpcf-type' => 'has',
|
484 |
-
'data-wpcf-value' => esc_attr($
|
485 |
'data-wpcf-message-disabled' => esc_attr__('This post type is disabled, becouse is used as parent post.', 'wpcf'),
|
486 |
),
|
487 |
);
|
488 |
// Check if it already belongs
|
489 |
-
if ( isset( $belongs[$
|
490 |
-
$options[$
|
491 |
-
$options[$
|
492 |
-
} else if ( isset( $has[$
|
493 |
-
$options[$
|
494 |
-
$options[$
|
495 |
}
|
496 |
}
|
497 |
$form['table-pr-has-form'] = array(
|
@@ -503,7 +517,7 @@ function wpcf_admin_metabox_relationship($post_type)
|
|
503 |
'#after' => '</ul>',
|
504 |
);
|
505 |
|
506 |
-
$form = wpcf_form(__FUNCTION__, $form);
|
507 |
echo $form->renderForm();
|
508 |
}
|
509 |
|
331 |
)
|
332 |
)
|
333 |
);
|
334 |
+
|
335 |
+
$custom_types = get_option( WPCF_OPTION_NAME_CUSTOM_TYPES, array() );
|
336 |
+
|
337 |
+
$is_error = false;
|
338 |
+
$error_message = '';
|
339 |
+
|
340 |
+
// Detect situations when we cannot configure post relationships yet. Render a message and finish.
|
341 |
+
$is_unsaved_post_type = ( ! isset( $_REQUEST['wpcf-post-type'] ) || ! isset( $custom_types[ $_REQUEST['wpcf-post-type'] ] ) );
|
342 |
+
if ( $is_unsaved_post_type ) {
|
343 |
+
$is_error = true;
|
344 |
+
$error_message = __( 'Please save first, before you can edit the relationship.', 'wpcf' );
|
345 |
+
}
|
346 |
+
|
347 |
+
$is_attachment = ( isset( $_REQUEST['wpcf-post-type'] ) && 'attachment' == $_REQUEST['wpcf-post-type'] );
|
348 |
+
if( $is_attachment ) {
|
349 |
+
$is_error = true;
|
350 |
+
$error_message = __( 'Post relationships are not allowed for the Media post type.', 'wpcf' );
|
351 |
+
}
|
352 |
+
|
353 |
+
if( $is_error ) {
|
354 |
$form['alert'] = array(
|
355 |
'#type' => 'notice',
|
356 |
+
'#markup' => $error_message,
|
357 |
);
|
358 |
+
$form = wpcf_form( __FUNCTION__, $form );
|
359 |
echo $form->renderForm();
|
360 |
+
return;
|
361 |
}
|
362 |
|
|
|
|
|
363 |
$post_type = $custom_types[$_REQUEST['wpcf-post-type']];
|
364 |
+
|
365 |
unset($custom_types);
|
366 |
|
367 |
+
// No problems detected, go ahead and render the options.
|
368 |
+
|
369 |
+
// belongs/children section
|
370 |
$has = wpcf_pr_admin_get_has( $post_type['slug'] );
|
371 |
$belongs = wpcf_pr_admin_get_belongs( $post_type['slug'] );
|
372 |
$post_types = get_post_types( '', 'objects' );
|
373 |
|
374 |
+
// parents
|
|
|
|
|
375 |
$form['parent-h3'] = array(
|
376 |
'#type' => 'markup',
|
377 |
'#markup' => sprintf(
|
389 |
);
|
390 |
$options = array();
|
391 |
|
392 |
+
// Build excluded post types
|
|
|
|
|
393 |
global $wpcf;
|
394 |
$excluded_post_types = $wpcf->excluded_post_types;
|
395 |
$excluded_post_types[] = $post_type['slug'];
|
396 |
+
// Explicitly exclude attachments for post relationships because there is no GUI for it
|
397 |
+
// (but we're not excluding them from all Types functionality)
|
398 |
+
$excluded_post_types[] = 'attachment';
|
399 |
|
400 |
+
foreach ( $post_types as $post_type_option_slug => $post_type_option ) {
|
401 |
+
|
402 |
+
$is_excluded = in_array( $post_type_option_slug, $excluded_post_types );
|
403 |
+
$has_no_ui = ( ! $post_type_option->show_ui && ! apply_filters('wpcf_show_ui_hide_in_relationships', true ) );
|
404 |
+
|
405 |
+
if ( $is_excluded || $has_no_ui ) {
|
|
|
|
|
406 |
continue;
|
407 |
}
|
408 |
+
|
409 |
+
$options[$post_type_option_slug] = array(
|
410 |
+
'#name' => 'ct[post_relationship][belongs][' . $post_type_option_slug . ']',
|
411 |
+
'#title' => $post_type_option->labels->singular_name,
|
412 |
+
'#default_value' => isset( $belongs[$post_type_option_slug] ),
|
413 |
'#inline' => true,
|
414 |
'#before' => '<li>',
|
415 |
'#after' => '</li>',
|
416 |
'#attributes' => array(
|
417 |
'class' => 'js-wpcf-relationship-checkbox',
|
418 |
'data-wpcf-type' => 'belongs',
|
419 |
+
'data-wpcf-value' => esc_attr($post_type_option_slug),
|
420 |
'data-wpcf-message-disabled' => esc_attr__('This post type is disabled, becouse is used as child post.', 'wpcf'),
|
421 |
),
|
422 |
);
|
423 |
+
if ( isset( $has[$post_type_option_slug] ) ) {
|
424 |
+
$options[$post_type_option_slug]['#before'] = '<li class="disabled">';
|
425 |
+
$options[$post_type_option_slug]['#attributes']['disabled'] = 'disabled';
|
426 |
}
|
427 |
}
|
428 |
$form['table-pr-belongs-form'] = array(
|
434 |
'#after' => '</ul>',
|
435 |
);
|
436 |
|
437 |
+
|
438 |
+
// child posts
|
|
|
439 |
$form['child-h3'] = array(
|
440 |
'#type' => 'markup',
|
441 |
'#markup' => sprintf(
|
452 |
)
|
453 |
);
|
454 |
$options = array();
|
455 |
+
foreach ( $post_types as $post_type_option_slug => $post_type_option ) {
|
456 |
if (
|
457 |
+
in_array( $post_type_option_slug, $excluded_post_types )
|
458 |
|| (
|
459 |
+
!$post_type_option->show_ui
|
460 |
&& !apply_filters('wpcf_show_ui_hide_in_relationships', true)
|
461 |
)
|
462 |
) {
|
466 |
$nonce = sprintf(
|
467 |
'child-post-fields-%s-%s',
|
468 |
$post_type['slug'],
|
469 |
+
$post_type_option_slug
|
470 |
);
|
471 |
$a = sprintf(
|
472 |
' <span>(<a class="js-wpcf-edit-child-post-fields" href="#" data-wpcf-nonce="%s" data-wpcf-child="%s" data-wpcf-parent="%s" data-wpcf-title="%s" data-wpcf-buttons-apply="%s" data-wpcf-buttons-cancel="%s" data-wpcf-message-loading="%s" data-wpcf-save-status="%s">%s</a>)</span>',
|
473 |
esc_attr(wp_create_nonce($nonce)),
|
474 |
+
esc_attr($post_type_option_slug),
|
475 |
esc_attr($post_type['slug']),
|
476 |
esc_attr(
|
477 |
sprintf(
|
478 |
__('Select child fields from %s to be displayed in Post Relationship table', 'wpcf'),
|
479 |
+
$post_type_option->labels->singular_name
|
480 |
)
|
481 |
),
|
482 |
esc_attr__('Apply', 'wpcf'),
|
483 |
esc_attr__('Cancel', 'wpcf'),
|
484 |
esc_attr__('Please Wait, Loading…', 'wpcf'),
|
485 |
+
esc_attr(isset( $has[$post_type_option_slug] )?'saved':'new'),
|
486 |
esc_attr__('Select fields', 'wpcf')
|
487 |
);
|
488 |
|
489 |
+
$options[$post_type_option_slug] = array(
|
490 |
+
'#name' => 'ct[post_relationship][has][' . $post_type_option_slug . ']',
|
491 |
+
'#title' => $post_type_option->labels->singular_name,
|
492 |
'#inline' => true,
|
493 |
'#before' => '<li>',
|
494 |
'#after' => $a.'</li>',
|
495 |
'#attributes' => array(
|
496 |
'class' => 'js-wpcf-relationship-checkbox',
|
497 |
'data-wpcf-type' => 'has',
|
498 |
+
'data-wpcf-value' => esc_attr($post_type_option_slug),
|
499 |
'data-wpcf-message-disabled' => esc_attr__('This post type is disabled, becouse is used as parent post.', 'wpcf'),
|
500 |
),
|
501 |
);
|
502 |
// Check if it already belongs
|
503 |
+
if ( isset( $belongs[$post_type_option_slug] ) ) {
|
504 |
+
$options[$post_type_option_slug]['#before'] = '<li class="disabled">';
|
505 |
+
$options[$post_type_option_slug]['#attributes']['disabled'] = 'disabled';
|
506 |
+
} else if ( isset( $has[$post_type_option_slug] ) ) {
|
507 |
+
$options[$post_type_option_slug]['#default_value'] = true;
|
508 |
+
$options[$post_type_option_slug]['#before'] = '<li class="active">';
|
509 |
}
|
510 |
}
|
511 |
$form['table-pr-has-form'] = array(
|
517 |
'#after' => '</ul>',
|
518 |
);
|
519 |
|
520 |
+
$form = wpcf_form( __FUNCTION__, $form );
|
521 |
echo $form->renderForm();
|
522 |
}
|
523 |
|
library/twig/twig/.travis.yml
CHANGED
@@ -5,7 +5,7 @@ sudo: false
|
|
5 |
cache:
|
6 |
directories:
|
7 |
- vendor
|
8 |
-
- $HOME/.composer/cache
|
9 |
|
10 |
php:
|
11 |
- 5.2
|
@@ -14,12 +14,16 @@ php:
|
|
14 |
- 5.5
|
15 |
- 5.6
|
16 |
- 7.0
|
|
|
17 |
- hhvm
|
18 |
|
19 |
env:
|
20 |
- TWIG_EXT=no
|
21 |
- TWIG_EXT=yes
|
22 |
|
|
|
|
|
|
|
23 |
install:
|
24 |
# Composer is not available on PHP 5.2
|
25 |
- if [ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]; then travis_retry composer install; fi
|
@@ -34,6 +38,7 @@ matrix:
|
|
34 |
exclude:
|
35 |
- php: hhvm
|
36 |
env: TWIG_EXT=yes
|
37 |
-
allow_failures:
|
38 |
- php: 7.0
|
39 |
env: TWIG_EXT=yes
|
|
|
|
5 |
cache:
|
6 |
directories:
|
7 |
- vendor
|
8 |
+
- $HOME/.composer/cache/files
|
9 |
|
10 |
php:
|
11 |
- 5.2
|
14 |
- 5.5
|
15 |
- 5.6
|
16 |
- 7.0
|
17 |
+
- 7.1
|
18 |
- hhvm
|
19 |
|
20 |
env:
|
21 |
- TWIG_EXT=no
|
22 |
- TWIG_EXT=yes
|
23 |
|
24 |
+
before_install:
|
25 |
+
- if [[ ! $TRAVIS_PHP_VERSION = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi
|
26 |
+
|
27 |
install:
|
28 |
# Composer is not available on PHP 5.2
|
29 |
- if [ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]; then travis_retry composer install; fi
|
38 |
exclude:
|
39 |
- php: hhvm
|
40 |
env: TWIG_EXT=yes
|
|
|
41 |
- php: 7.0
|
42 |
env: TWIG_EXT=yes
|
43 |
+
- php: 7.1
|
44 |
+
env: TWIG_EXT=yes
|
library/twig/twig/CHANGELOG
CHANGED
@@ -1,3 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
* 1.25.0 (2016-09-21)
|
2 |
|
3 |
* changed the way we store template source in template classes
|
1 |
+
* 1.28.2 (2016-11-23)
|
2 |
+
|
3 |
+
* fixed precedence between getFoo() and isFoo() in Twig_Template::getAttribute()
|
4 |
+
* improved a deprecation message
|
5 |
+
|
6 |
+
* 1.28.1 (2016-11-18)
|
7 |
+
|
8 |
+
* fixed block() function when used with a template argument
|
9 |
+
|
10 |
+
* 1.28.0 (2016-11-17)
|
11 |
+
|
12 |
+
* added support for the PHP 7 null coalescing operator for the ?? Twig implementation
|
13 |
+
* exposed a way to access template data and methods in a portable way
|
14 |
+
* changed context access to use the PHP 7 null coalescing operator when available
|
15 |
+
* added the "with" tag
|
16 |
+
* added support for a custom template on the block() function
|
17 |
+
* added "is defined" support for block() and constant()
|
18 |
+
* optimized the way attributes are fetched
|
19 |
+
|
20 |
+
* 1.27.0 (2016-10-25)
|
21 |
+
|
22 |
+
* deprecated Twig_Parser::getEnvironment()
|
23 |
+
* deprecated Twig_Parser::addHandler() and Twig_Parser::addNodeVisitor()
|
24 |
+
* deprecated Twig_Compiler::addIndentation()
|
25 |
+
* fixed regression when registering two extensions having the same class name
|
26 |
+
* deprecated Twig_LoaderInterface::getSource() (implement Twig_SourceContextLoaderInterface instead)
|
27 |
+
* fixed the filesystem loader with relative paths
|
28 |
+
* deprecated Twig_Node::getLine() in favor of Twig_Node::getTemplateLine()
|
29 |
+
* deprecated Twig_Template::getSource() in favor of Twig_Template::getSourceContext()
|
30 |
+
* deprecated Twig_Node::getFilename() in favor of Twig_Node::getTemplateName()
|
31 |
+
* deprecated the "filename" escaping strategy (use "name" instead)
|
32 |
+
* added Twig_Source to hold information about the original template
|
33 |
+
* deprecated Twig_Error::getTemplateFile() and Twig_Error::setTemplateFile() in favor of Twig_Error::getTemplateName() and Twig_Error::setTemplateName()
|
34 |
+
* deprecated Parser::getFilename()
|
35 |
+
* fixed template paths when a template name contains a protocol like vfs://
|
36 |
+
* improved debugging with Twig_Sandbox_SecurityError exceptions for disallowed methods and properties
|
37 |
+
|
38 |
+
* 1.26.1 (2016-10-05)
|
39 |
+
|
40 |
+
* removed template source code from generated template classes when debug is disabled
|
41 |
+
* fixed default implementation of Twig_Template::getDebugInfo() for better BC
|
42 |
+
* fixed regression on static calls for functions/filters/tests
|
43 |
+
|
44 |
+
* 1.26.0 (2016-10-02)
|
45 |
+
|
46 |
+
* added template cache invalidation based on more environment options
|
47 |
+
* added a missing deprecation notice
|
48 |
+
* fixed template paths when a template is stored in a PHAR file
|
49 |
+
* allowed filters/functions/tests implementation to use a different class than the extension they belong to
|
50 |
+
* deprecated Twig_ExtensionInterface::getName()
|
51 |
+
|
52 |
* 1.25.0 (2016-09-21)
|
53 |
|
54 |
* changed the way we store template source in template classes
|
library/twig/twig/doc/advanced.rst
CHANGED
@@ -136,7 +136,13 @@ Creating a filter is as simple as associating a name with a PHP callable::
|
|
136 |
// or a simple PHP function
|
137 |
$filter = new Twig_SimpleFilter('rot13', 'str_rot13');
|
138 |
|
|
|
|
|
|
|
|
|
139 |
// or a class method
|
|
|
|
|
140 |
$filter = new Twig_SimpleFilter('rot13', array('SomeClass', 'rot13Filter'));
|
141 |
|
142 |
The first argument passed to the ``Twig_SimpleFilter`` constructor is the name
|
@@ -525,10 +531,6 @@ reusable class like adding support for internationalization. An extension can
|
|
525 |
define tags, filters, tests, operators, global variables, functions, and node
|
526 |
visitors.
|
527 |
|
528 |
-
Creating an extension also makes for a better separation of code that is
|
529 |
-
executed at compilation time and code needed at runtime. As such, it makes
|
530 |
-
your code faster.
|
531 |
-
|
532 |
Most of the time, it is useful to create a single extension for your project,
|
533 |
to host all the specific tags and filters you want to add to Twig.
|
534 |
|
@@ -552,8 +554,6 @@ An extension is a class that implements the following interface::
|
|
552 |
*
|
553 |
* This is where you can load some file that contains filter functions for instance.
|
554 |
*
|
555 |
-
* @param Twig_Environment $environment The current Twig_Environment instance
|
556 |
-
*
|
557 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
558 |
*/
|
559 |
function initRuntime(Twig_Environment $environment);
|
@@ -561,35 +561,35 @@ An extension is a class that implements the following interface::
|
|
561 |
/**
|
562 |
* Returns the token parser instances to add to the existing list.
|
563 |
*
|
564 |
-
* @return
|
565 |
*/
|
566 |
function getTokenParsers();
|
567 |
|
568 |
/**
|
569 |
* Returns the node visitor instances to add to the existing list.
|
570 |
*
|
571 |
-
* @return
|
572 |
*/
|
573 |
function getNodeVisitors();
|
574 |
|
575 |
/**
|
576 |
* Returns a list of filters to add to the existing list.
|
577 |
*
|
578 |
-
* @return
|
579 |
*/
|
580 |
function getFilters();
|
581 |
|
582 |
/**
|
583 |
* Returns a list of tests to add to the existing list.
|
584 |
*
|
585 |
-
* @return
|
586 |
*/
|
587 |
function getTests();
|
588 |
|
589 |
/**
|
590 |
* Returns a list of functions to add to the existing list.
|
591 |
*
|
592 |
-
* @return
|
593 |
*/
|
594 |
function getFunctions();
|
595 |
|
@@ -613,32 +613,27 @@ An extension is a class that implements the following interface::
|
|
613 |
* Returns the name of the extension.
|
614 |
*
|
615 |
* @return string The extension name
|
|
|
|
|
616 |
*/
|
617 |
function getName();
|
618 |
}
|
619 |
|
620 |
-
To keep your extension class clean and lean,
|
621 |
-
``Twig_Extension`` class instead of implementing the
|
622 |
-
|
623 |
-
``Twig_Extension`` provides empty implementations for all other methods.
|
624 |
-
|
625 |
-
The ``getName()`` method must return a unique identifier for your extension.
|
626 |
-
|
627 |
-
Now, with this information in mind, let's create the most basic extension
|
628 |
-
possible::
|
629 |
|
630 |
class Project_Twig_Extension extends Twig_Extension
|
631 |
{
|
632 |
-
public function getName()
|
633 |
-
{
|
634 |
-
return 'project';
|
635 |
-
}
|
636 |
}
|
637 |
|
|
|
|
|
|
|
638 |
.. note::
|
639 |
|
640 |
-
|
641 |
-
the
|
642 |
|
643 |
Twig does not care where you save your extension on the filesystem, as all
|
644 |
extensions must be registered explicitly to be available in your templates.
|
@@ -651,7 +646,7 @@ main ``Environment`` object::
|
|
651 |
|
652 |
.. tip::
|
653 |
|
654 |
-
The
|
655 |
|
656 |
Globals
|
657 |
~~~~~~~
|
@@ -770,6 +765,101 @@ The ``getTests()`` method lets you add new test functions::
|
|
770 |
// ...
|
771 |
}
|
772 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
773 |
Overloading
|
774 |
-----------
|
775 |
|
@@ -790,11 +880,6 @@ possible** (order matters)::
|
|
790 |
{
|
791 |
// do something different from the built-in date filter
|
792 |
}
|
793 |
-
|
794 |
-
public function getName()
|
795 |
-
{
|
796 |
-
return 'project';
|
797 |
-
}
|
798 |
}
|
799 |
|
800 |
$twig = new Twig_Environment($loader);
|
@@ -802,7 +887,7 @@ possible** (order matters)::
|
|
802 |
|
803 |
Here, we have overloaded the built-in ``date`` filter with a custom one.
|
804 |
|
805 |
-
If you do the same on the Twig_Environment itself, beware that it takes
|
806 |
precedence over any other registered extensions::
|
807 |
|
808 |
$twig = new Twig_Environment($loader);
|
136 |
// or a simple PHP function
|
137 |
$filter = new Twig_SimpleFilter('rot13', 'str_rot13');
|
138 |
|
139 |
+
// or a class static method
|
140 |
+
$filter = new Twig_SimpleFilter('rot13', array('SomeClass', 'rot13Filter'));
|
141 |
+
$filter = new Twig_SimpleFilter('rot13', 'SomeClass::rot13Filter');
|
142 |
+
|
143 |
// or a class method
|
144 |
+
$filter = new Twig_SimpleFilter('rot13', array($this, 'rot13Filter'));
|
145 |
+
// the one below needs a runtime implementation (see below for more information)
|
146 |
$filter = new Twig_SimpleFilter('rot13', array('SomeClass', 'rot13Filter'));
|
147 |
|
148 |
The first argument passed to the ``Twig_SimpleFilter`` constructor is the name
|
531 |
define tags, filters, tests, operators, global variables, functions, and node
|
532 |
visitors.
|
533 |
|
|
|
|
|
|
|
|
|
534 |
Most of the time, it is useful to create a single extension for your project,
|
535 |
to host all the specific tags and filters you want to add to Twig.
|
536 |
|
554 |
*
|
555 |
* This is where you can load some file that contains filter functions for instance.
|
556 |
*
|
|
|
|
|
557 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
558 |
*/
|
559 |
function initRuntime(Twig_Environment $environment);
|
561 |
/**
|
562 |
* Returns the token parser instances to add to the existing list.
|
563 |
*
|
564 |
+
* @return (Twig_TokenParserInterface|Twig_TokenParserBrokerInterface)[]
|
565 |
*/
|
566 |
function getTokenParsers();
|
567 |
|
568 |
/**
|
569 |
* Returns the node visitor instances to add to the existing list.
|
570 |
*
|
571 |
+
* @return Twig_NodeVisitorInterface[]
|
572 |
*/
|
573 |
function getNodeVisitors();
|
574 |
|
575 |
/**
|
576 |
* Returns a list of filters to add to the existing list.
|
577 |
*
|
578 |
+
* @return Twig_SimpleFilter[]
|
579 |
*/
|
580 |
function getFilters();
|
581 |
|
582 |
/**
|
583 |
* Returns a list of tests to add to the existing list.
|
584 |
*
|
585 |
+
* @return Twig_SimpleTest[]
|
586 |
*/
|
587 |
function getTests();
|
588 |
|
589 |
/**
|
590 |
* Returns a list of functions to add to the existing list.
|
591 |
*
|
592 |
+
* @return Twig_SimpleFunction[]
|
593 |
*/
|
594 |
function getFunctions();
|
595 |
|
613 |
* Returns the name of the extension.
|
614 |
*
|
615 |
* @return string The extension name
|
616 |
+
*
|
617 |
+
* @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
|
618 |
*/
|
619 |
function getName();
|
620 |
}
|
621 |
|
622 |
+
To keep your extension class clean and lean, inherit from the built-in
|
623 |
+
``Twig_Extension`` class instead of implementing the interface as it provides
|
624 |
+
empty implementations for all methods:
|
|
|
|
|
|
|
|
|
|
|
|
|
625 |
|
626 |
class Project_Twig_Extension extends Twig_Extension
|
627 |
{
|
|
|
|
|
|
|
|
|
628 |
}
|
629 |
|
630 |
+
Of course, this extension does nothing for now. We will customize it in the
|
631 |
+
next sections.
|
632 |
+
|
633 |
.. note::
|
634 |
|
635 |
+
Prior to Twig 1.26, you must implement the ``getName()`` method which must
|
636 |
+
return a unique identifier for the extension.
|
637 |
|
638 |
Twig does not care where you save your extension on the filesystem, as all
|
639 |
extensions must be registered explicitly to be available in your templates.
|
646 |
|
647 |
.. tip::
|
648 |
|
649 |
+
The Twig core extensions are great examples of how extensions work.
|
650 |
|
651 |
Globals
|
652 |
~~~~~~~
|
765 |
// ...
|
766 |
}
|
767 |
|
768 |
+
Definition vs Runtime
|
769 |
+
~~~~~~~~~~~~~~~~~~~~~
|
770 |
+
|
771 |
+
Twig filters, functions, and tests runtime implementations can be defined as
|
772 |
+
any valid PHP callable:
|
773 |
+
|
774 |
+
* **functions/static methods**: Simple to implement and fast (used by all Twig
|
775 |
+
core extensions); but it is hard for the runtime to depend on external
|
776 |
+
objects;
|
777 |
+
|
778 |
+
* **closures**: Simple to implement;
|
779 |
+
|
780 |
+
* **object methods**: More flexible and required if your runtime code depends
|
781 |
+
on external objects.
|
782 |
+
|
783 |
+
The simplest way to use methods is to define them on the extension itself::
|
784 |
+
|
785 |
+
class Project_Twig_Extension extends Twig_Extension
|
786 |
+
{
|
787 |
+
private $rot13Provider;
|
788 |
+
|
789 |
+
public function __construct($rot13Provider)
|
790 |
+
{
|
791 |
+
$this->rot13Provider = $rot13Provider;
|
792 |
+
}
|
793 |
+
|
794 |
+
public function getFunctions()
|
795 |
+
{
|
796 |
+
return array(
|
797 |
+
new Twig_SimpleFunction('rot13', array($this, 'rot13')),
|
798 |
+
);
|
799 |
+
}
|
800 |
+
|
801 |
+
public function rot13($value)
|
802 |
+
{
|
803 |
+
return $rot13Provider->rot13($value);
|
804 |
+
}
|
805 |
+
}
|
806 |
+
|
807 |
+
This is very convenient but not recommended as it makes template compilation
|
808 |
+
depend on runtime dependencies even if they are not needed (think for instance
|
809 |
+
as a dependency that connects to a database engine).
|
810 |
+
|
811 |
+
As of Twig 1.26, you can easily decouple the extension definitions from their
|
812 |
+
runtime implementations by registering a ``Twig_RuntimeLoaderInterface``
|
813 |
+
instance on the environment that knows how to instantiate such runtime classes
|
814 |
+
(runtime classes must be autoload-able)::
|
815 |
+
|
816 |
+
class RuntimeLoader implements Twig_RuntimeLoaderInterface
|
817 |
+
{
|
818 |
+
public function load($class)
|
819 |
+
{
|
820 |
+
// implement the logic to create an instance of $class
|
821 |
+
// and inject its dependencies
|
822 |
+
// most of the time, it means using your dependency injection container
|
823 |
+
if ('Project_Twig_RuntimeExtension' === $class) {
|
824 |
+
return new $class(new Rot13Provider());
|
825 |
+
} else {
|
826 |
+
// ...
|
827 |
+
}
|
828 |
+
}
|
829 |
+
}
|
830 |
+
|
831 |
+
$twig->addRuntimeLoader(new RuntimeLoader());
|
832 |
+
|
833 |
+
It is now possible to move the runtime logic to a new
|
834 |
+
``Project_Twig_RuntimeExtension`` class and use it directly in the extension::
|
835 |
+
|
836 |
+
class Project_Twig_RuntimeExtension extends Twig_Extension
|
837 |
+
{
|
838 |
+
private $rot13Provider;
|
839 |
+
|
840 |
+
public function __construct($rot13Provider)
|
841 |
+
{
|
842 |
+
$this->rot13Provider = $rot13Provider;
|
843 |
+
}
|
844 |
+
|
845 |
+
public function rot13($value)
|
846 |
+
{
|
847 |
+
return $rot13Provider->rot13($value);
|
848 |
+
}
|
849 |
+
}
|
850 |
+
|
851 |
+
class Project_Twig_Extension extends Twig_Extension
|
852 |
+
{
|
853 |
+
public function getFunctions()
|
854 |
+
{
|
855 |
+
return array(
|
856 |
+
new Twig_SimpleFunction('rot13', array('Project_Twig_RuntimeExtension', 'rot13')),
|
857 |
+
// or
|
858 |
+
new Twig_SimpleFunction('rot13', 'Project_Twig_RuntimeExtension::rot13'),
|
859 |
+
);
|
860 |
+
}
|
861 |
+
}
|
862 |
+
|
863 |
Overloading
|
864 |
-----------
|
865 |
|
880 |
{
|
881 |
// do something different from the built-in date filter
|
882 |
}
|
|
|
|
|
|
|
|
|
|
|
883 |
}
|
884 |
|
885 |
$twig = new Twig_Environment($loader);
|
887 |
|
888 |
Here, we have overloaded the built-in ``date`` filter with a custom one.
|
889 |
|
890 |
+
If you do the same on the ``Twig_Environment`` itself, beware that it takes
|
891 |
precedence over any other registered extensions::
|
892 |
|
893 |
$twig = new Twig_Environment($loader);
|
library/twig/twig/doc/advanced_legacy.rst
CHANGED
@@ -539,43 +539,41 @@ An extension is a class that implements the following interface::
|
|
539 |
* Initializes the runtime environment.
|
540 |
*
|
541 |
* This is where you can load some file that contains filter functions for instance.
|
542 |
-
*
|
543 |
-
* @param Twig_Environment $environment The current Twig_Environment instance
|
544 |
*/
|
545 |
function initRuntime(Twig_Environment $environment);
|
546 |
|
547 |
/**
|
548 |
* Returns the token parser instances to add to the existing list.
|
549 |
*
|
550 |
-
* @return
|
551 |
*/
|
552 |
function getTokenParsers();
|
553 |
|
554 |
/**
|
555 |
* Returns the node visitor instances to add to the existing list.
|
556 |
*
|
557 |
-
* @return
|
558 |
*/
|
559 |
function getNodeVisitors();
|
560 |
|
561 |
/**
|
562 |
* Returns a list of filters to add to the existing list.
|
563 |
*
|
564 |
-
* @return
|
565 |
*/
|
566 |
function getFilters();
|
567 |
|
568 |
/**
|
569 |
* Returns a list of tests to add to the existing list.
|
570 |
*
|
571 |
-
* @return
|
572 |
*/
|
573 |
function getTests();
|
574 |
|
575 |
/**
|
576 |
* Returns a list of functions to add to the existing list.
|
577 |
*
|
578 |
-
* @return
|
579 |
*/
|
580 |
function getFunctions();
|
581 |
|
539 |
* Initializes the runtime environment.
|
540 |
*
|
541 |
* This is where you can load some file that contains filter functions for instance.
|
|
|
|
|
542 |
*/
|
543 |
function initRuntime(Twig_Environment $environment);
|
544 |
|
545 |
/**
|
546 |
* Returns the token parser instances to add to the existing list.
|
547 |
*
|
548 |
+
* @return (Twig_TokenParserInterface|Twig_TokenParserBrokerInterface)[]
|
549 |
*/
|
550 |
function getTokenParsers();
|
551 |
|
552 |
/**
|
553 |
* Returns the node visitor instances to add to the existing list.
|
554 |
*
|
555 |
+
* @return Twig_NodeVisitorInterface[]
|
556 |
*/
|
557 |
function getNodeVisitors();
|
558 |
|
559 |
/**
|
560 |
* Returns a list of filters to add to the existing list.
|
561 |
*
|
562 |
+
* @return Twig_SimpleFilter[]
|
563 |
*/
|
564 |
function getFilters();
|
565 |
|
566 |
/**
|
567 |
* Returns a list of tests to add to the existing list.
|
568 |
*
|
569 |
+
* @return Twig_SimpleTest[]
|
570 |
*/
|
571 |
function getTests();
|
572 |
|
573 |
/**
|
574 |
* Returns a list of functions to add to the existing list.
|
575 |
*
|
576 |
+
* @return Twig_SimpleFunction[]
|
577 |
*/
|
578 |
function getFunctions();
|
579 |
|
library/twig/twig/doc/api.rst
CHANGED
@@ -43,10 +43,18 @@ templates from a database or other resources.
|
|
43 |
the evaluated templates. For such a need, you can use any available PHP
|
44 |
cache library.
|
45 |
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
-
|
|
|
50 |
|
51 |
To render the template with some variables, call the ``render()`` method::
|
52 |
|
@@ -60,6 +68,14 @@ You can also load and render the template in one fell swoop::
|
|
60 |
|
61 |
echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here'));
|
62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
.. _environment_options:
|
64 |
|
65 |
Environment Options
|
@@ -115,14 +131,14 @@ The following options are available:
|
|
115 |
``false`` to disable).
|
116 |
|
117 |
As of Twig 1.9, you can set the escaping strategy to use (``css``, ``url``,
|
118 |
-
``html_attr``, or a PHP callback that takes the template
|
119 |
return the escaping strategy to use -- the callback cannot be a function name
|
120 |
to avoid collision with built-in escaping strategies).
|
121 |
|
122 |
-
As of Twig 1.17, the ``filename`` escaping strategy
|
123 |
-
strategy to use for a template based on
|
124 |
-
strategy does not incur any overhead at
|
125 |
-
compilation time.)
|
126 |
|
127 |
* ``optimizations`` *integer*
|
128 |
|
@@ -156,6 +172,9 @@ Here is a list of the built-in loaders Twig provides:
|
|
156 |
.. versionadded:: 1.10
|
157 |
The ``prependPath()`` and support for namespaces were added in Twig 1.10.
|
158 |
|
|
|
|
|
|
|
159 |
``Twig_Loader_Filesystem`` loads templates from the file system. This loader
|
160 |
can find templates in folders on the file system and is the preferred way to
|
161 |
load them::
|
@@ -190,6 +209,18 @@ Namespaced templates can be accessed via the special
|
|
190 |
|
191 |
$twig->render('@admin/index.html', array());
|
192 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
``Twig_Loader_Array``
|
194 |
.....................
|
195 |
|
@@ -256,6 +287,8 @@ All loaders implement the ``Twig_LoaderInterface``::
|
|
256 |
* @param string $name string The name of the template to load
|
257 |
*
|
258 |
* @return string The template source code
|
|
|
|
|
259 |
*/
|
260 |
function getSource($name);
|
261 |
|
@@ -280,6 +313,11 @@ All loaders implement the ``Twig_LoaderInterface``::
|
|
280 |
The ``isFresh()`` method must return ``true`` if the current cached template
|
281 |
is still fresh, given the last modification time, or ``false`` otherwise.
|
282 |
|
|
|
|
|
|
|
|
|
|
|
283 |
.. tip::
|
284 |
|
285 |
As of Twig 1.11.0, you can also implement ``Twig_ExistsLoaderInterface``
|
43 |
the evaluated templates. For such a need, you can use any available PHP
|
44 |
cache library.
|
45 |
|
46 |
+
Rendering Templates
|
47 |
+
-------------------
|
48 |
+
|
49 |
+
To load a template from a Twig environment, call the ``load()`` method which
|
50 |
+
returns a ``Twig_TemplateWrapper`` instance::
|
51 |
+
|
52 |
+
$template = $twig->load('index.html');
|
53 |
+
|
54 |
+
.. note::
|
55 |
|
56 |
+
Before Twig 1.28, you should use ``loadTemplate()`` instead which returns a
|
57 |
+
``Twig_Template`` instance.
|
58 |
|
59 |
To render the template with some variables, call the ``render()`` method::
|
60 |
|
68 |
|
69 |
echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here'));
|
70 |
|
71 |
+
.. versionadded:: 1.28
|
72 |
+
The possibility to render blocks from the API was added in Twig 1.28.
|
73 |
+
|
74 |
+
If a template defines blocks, they can be rendered individually via the
|
75 |
+
``renderBlock()`` call::
|
76 |
+
|
77 |
+
echo $template->renderBlock('block_name', array('the' => 'variables', 'go' => 'here'));
|
78 |
+
|
79 |
.. _environment_options:
|
80 |
|
81 |
Environment Options
|
131 |
``false`` to disable).
|
132 |
|
133 |
As of Twig 1.9, you can set the escaping strategy to use (``css``, ``url``,
|
134 |
+
``html_attr``, or a PHP callback that takes the template name and must
|
135 |
return the escaping strategy to use -- the callback cannot be a function name
|
136 |
to avoid collision with built-in escaping strategies).
|
137 |
|
138 |
+
As of Twig 1.17, the ``filename`` escaping strategy (renamed to ``name`` as
|
139 |
+
of Twig 1.27) determines the escaping strategy to use for a template based on
|
140 |
+
the template filename extension (this strategy does not incur any overhead at
|
141 |
+
runtime as auto-escaping is done at compilation time.)
|
142 |
|
143 |
* ``optimizations`` *integer*
|
144 |
|
172 |
.. versionadded:: 1.10
|
173 |
The ``prependPath()`` and support for namespaces were added in Twig 1.10.
|
174 |
|
175 |
+
.. versionadded:: 1.27
|
176 |
+
Relative paths support was added in Twig 1.27.
|
177 |
+
|
178 |
``Twig_Loader_Filesystem`` loads templates from the file system. This loader
|
179 |
can find templates in folders on the file system and is the preferred way to
|
180 |
load them::
|
209 |
|
210 |
$twig->render('@admin/index.html', array());
|
211 |
|
212 |
+
``Twig_Loader_Filesystem`` support absolute and relative paths. Using relative
|
213 |
+
paths is preferred as it makes the cache keys independent of the project root
|
214 |
+
directory (for instance, it allows warming the cache from a build server where
|
215 |
+
the directory might be different from the one used on production servers)::
|
216 |
+
|
217 |
+
$loader = new Twig_Loader_Filesystem('templates', getcwd().'/..');
|
218 |
+
|
219 |
+
.. note::
|
220 |
+
|
221 |
+
When not passing the root path as a second argument, Twig uses ``getcwd()``
|
222 |
+
for relative paths.
|
223 |
+
|
224 |
``Twig_Loader_Array``
|
225 |
.....................
|
226 |
|
287 |
* @param string $name string The name of the template to load
|
288 |
*
|
289 |
* @return string The template source code
|
290 |
+
*
|
291 |
+
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
|
292 |
*/
|
293 |
function getSource($name);
|
294 |
|
313 |
The ``isFresh()`` method must return ``true`` if the current cached template
|
314 |
is still fresh, given the last modification time, or ``false`` otherwise.
|
315 |
|
316 |
+
.. note::
|
317 |
+
|
318 |
+
As of Twig 1.27, you should also implement
|
319 |
+
``Twig_SourceContextLoaderInterface`` to avoid deprecation notices.
|
320 |
+
|
321 |
.. tip::
|
322 |
|
323 |
As of Twig 1.11.0, you can also implement ``Twig_ExistsLoaderInterface``
|
library/twig/twig/doc/deprecated.rst
CHANGED
@@ -20,6 +20,11 @@ Token Parsers
|
|
20 |
* ``Twig_TokenParserBrokerInterface``
|
21 |
* ``Twig_TokenParserBroker``
|
22 |
|
|
|
|
|
|
|
|
|
|
|
23 |
Extensions
|
24 |
----------
|
25 |
|
@@ -37,6 +42,9 @@ Extensions
|
|
37 |
deprecated. Implement ``Twig_Extension_GlobalsInterface`` to avoid
|
38 |
deprecation notices.
|
39 |
|
|
|
|
|
|
|
40 |
PEAR
|
41 |
----
|
42 |
|
@@ -109,6 +117,17 @@ Nodes
|
|
109 |
* As of Twig 1.x, ``Node::toXml()`` is deprecated and will be removed in Twig
|
110 |
2.0.
|
111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
Interfaces
|
113 |
----------
|
114 |
|
@@ -120,16 +139,30 @@ Interfaces
|
|
120 |
* ``Twig_NodeInterface`` (use ``Twig_Node`` instead)
|
121 |
* ``Twig_ParserInterface`` (use ``Twig_Parser`` instead)
|
122 |
* ``Twig_ExistsLoaderInterface`` (merged with ``Twig_LoaderInterface``)
|
|
|
123 |
* ``Twig_TemplateInterface`` (use ``Twig_Template`` instead, and use
|
124 |
those constants Twig_Template::ANY_CALL, Twig_Template::ARRAY_CALL,
|
125 |
Twig_Template::METHOD_CALL)
|
126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
Loaders
|
128 |
-------
|
129 |
|
130 |
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
|
131 |
2.0. You can render a string via ``Twig_Environment::createTemplate()``.
|
132 |
|
|
|
|
|
|
|
|
|
133 |
Node Visitors
|
134 |
-------------
|
135 |
|
@@ -153,10 +186,25 @@ Globals
|
|
153 |
Miscellaneous
|
154 |
-------------
|
155 |
|
156 |
-
* As of Twig 1.x, ``Twig_Environment::clearTemplateCache()``,
|
157 |
-
``Twig_Environment::
|
158 |
-
``Twig_Environment::
|
|
|
|
|
|
|
|
|
159 |
|
160 |
* As of Twig 1.x, ``Twig_Template::getEnvironment()`` and
|
161 |
``Twig_TemplateInterface::getEnvironment()`` are deprecated and will be
|
162 |
removed in 2.0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
* ``Twig_TokenParserBrokerInterface``
|
21 |
* ``Twig_TokenParserBroker``
|
22 |
|
23 |
+
* As of Twig 1.27, ``Twig_Parser::getFilename()`` is deprecated. From a token
|
24 |
+
parser, use ``$this->parser->getStream()->getSourceContext()->getPath()`` instead.
|
25 |
+
|
26 |
+
* As of Twig 1.27, ``Twig_Parser::getEnvironment()`` is deprecated.
|
27 |
+
|
28 |
Extensions
|
29 |
----------
|
30 |
|
42 |
deprecated. Implement ``Twig_Extension_GlobalsInterface`` to avoid
|
43 |
deprecation notices.
|
44 |
|
45 |
+
* As of Twig 1.26, the ``Twig_ExtensionInterface::getName()`` method is
|
46 |
+
deprecated and it is not used internally anymore.
|
47 |
+
|
48 |
PEAR
|
49 |
----
|
50 |
|
117 |
* As of Twig 1.x, ``Node::toXml()`` is deprecated and will be removed in Twig
|
118 |
2.0.
|
119 |
|
120 |
+
* As of Twig 1.26, ``Node::$nodes`` should only contains ``Twig_Node``
|
121 |
+
instances, storing a ``null`` value is deprecated and won't be possible in
|
122 |
+
Twig 2.x.
|
123 |
+
|
124 |
+
* As of Twig 1.27, the ``filename`` attribute on ``Twig_Node_Module`` is
|
125 |
+
deprecated. Use ``getName()`` instead.
|
126 |
+
|
127 |
+
* As of Twig 1.27, the ``Twig_Node::getFilename()/Twig_Node::getLine()``
|
128 |
+
methods are deprecated, use
|
129 |
+
``Twig_Node::getTemplateName()/Twig_Node::getTemplateLine()`` instead.
|
130 |
+
|
131 |
Interfaces
|
132 |
----------
|
133 |
|
139 |
* ``Twig_NodeInterface`` (use ``Twig_Node`` instead)
|
140 |
* ``Twig_ParserInterface`` (use ``Twig_Parser`` instead)
|
141 |
* ``Twig_ExistsLoaderInterface`` (merged with ``Twig_LoaderInterface``)
|
142 |
+
* ``Twig_SourceContextLoaderInterface`` (merged with ``Twig_LoaderInterface``)
|
143 |
* ``Twig_TemplateInterface`` (use ``Twig_Template`` instead, and use
|
144 |
those constants Twig_Template::ANY_CALL, Twig_Template::ARRAY_CALL,
|
145 |
Twig_Template::METHOD_CALL)
|
146 |
|
147 |
+
Compiler
|
148 |
+
--------
|
149 |
+
|
150 |
+
* As of Twig 1.26, the ``Twig_Compiler::getFilename()`` has been deprecated.
|
151 |
+
You should not use it anyway as its values is not reliable.
|
152 |
+
|
153 |
+
* As of Twig 1.27, the ``Twig_Compiler::addIndentation()`` has been deprecated.
|
154 |
+
Use ``Twig_Compiler::write('')`` instead.
|
155 |
+
|
156 |
Loaders
|
157 |
-------
|
158 |
|
159 |
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
|
160 |
2.0. You can render a string via ``Twig_Environment::createTemplate()``.
|
161 |
|
162 |
+
* As of Twig 1.27, ``Twig_LoaderInterface::getSource()`` is deprecated.
|
163 |
+
Implement ``Twig_SourceContextLoaderInterface`` instead and use
|
164 |
+
``getSourceContext()``.
|
165 |
+
|
166 |
Node Visitors
|
167 |
-------------
|
168 |
|
186 |
Miscellaneous
|
187 |
-------------
|
188 |
|
189 |
+
* As of Twig 1.x, ``Twig_Environment::clearTemplateCache()``,
|
190 |
+
``Twig_Environment::writeCacheFile()``,
|
191 |
+
``Twig_Environment::clearCacheFiles()``,
|
192 |
+
``Twig_Environment::getCacheFilename()``,
|
193 |
+
``Twig_Environment::getTemplateClassPrefix()``,
|
194 |
+
``Twig_Environment::getLexer()``, ``Twig_Environment::getParser()``, and
|
195 |
+
``Twig_Environment::getCompiler()`` are deprecated and will be removed in 2.0.
|
196 |
|
197 |
* As of Twig 1.x, ``Twig_Template::getEnvironment()`` and
|
198 |
``Twig_TemplateInterface::getEnvironment()`` are deprecated and will be
|
199 |
removed in 2.0.
|
200 |
+
|
201 |
+
* As of Twig 1.27, ``Twig_Error::getTemplateFile()`` and
|
202 |
+
``Twig_Error::setTemplateFile()`` are deprecated. Use
|
203 |
+
``Twig_Error::getTemplateName()`` and ``Twig_Error::setTemplateName()``
|
204 |
+
instead.
|
205 |
+
|
206 |
+
* As of Twig 1.27, ``Twig_Template::getSource()`` is deprecated. Use
|
207 |
+
``Twig_Template::getSourceContext()`` instead.
|
208 |
+
|
209 |
+
* As of Twig 1.27, ``Twig_Parser::addHandler()`` and
|
210 |
+
``Twig_Parser::addNodeVisitor()`` are deprecated and will be removed in 2.0.
|
library/twig/twig/doc/filters/date.rst
CHANGED
@@ -54,6 +54,9 @@ dates and the second one is the default format for date intervals:
|
|
54 |
.. code-block:: php
|
55 |
|
56 |
$twig = new Twig_Environment($loader);
|
|
|
|
|
|
|
57 |
$twig->getExtension('core')->setDateFormat('d/m/Y', '%d days');
|
58 |
|
59 |
Timezone
|
@@ -79,6 +82,9 @@ The default timezone can also be set globally by calling ``setTimezone()``:
|
|
79 |
.. code-block:: php
|
80 |
|
81 |
$twig = new Twig_Environment($loader);
|
|
|
|
|
|
|
82 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
83 |
|
84 |
Arguments
|
54 |
.. code-block:: php
|
55 |
|
56 |
$twig = new Twig_Environment($loader);
|
57 |
+
$twig->getExtension('Twig_Extension_Core')->setDateFormat('d/m/Y', '%d days');
|
58 |
+
|
59 |
+
// before Twig 1.26
|
60 |
$twig->getExtension('core')->setDateFormat('d/m/Y', '%d days');
|
61 |
|
62 |
Timezone
|
82 |
.. code-block:: php
|
83 |
|
84 |
$twig = new Twig_Environment($loader);
|
85 |
+
$twig->getExtension('Twig_Extension_Core')->setTimezone('Europe/Paris');
|
86 |
+
|
87 |
+
// before Twig 1.26
|
88 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
89 |
|
90 |
Arguments
|
library/twig/twig/doc/filters/escape.rst
CHANGED
@@ -97,6 +97,9 @@ used in the ``escape`` call) and the second one must be a valid PHP callable:
|
|
97 |
.. code-block:: php
|
98 |
|
99 |
$twig = new Twig_Environment($loader);
|
|
|
|
|
|
|
100 |
$twig->getExtension('core')->setEscaper('csv', 'csv_escaper');
|
101 |
|
102 |
When called by Twig, the callable receives the Twig environment instance, the
|
97 |
.. code-block:: php
|
98 |
|
99 |
$twig = new Twig_Environment($loader);
|
100 |
+
$twig->getExtension('Twig_Extension_Core')->setEscaper('csv', 'csv_escaper');
|
101 |
+
|
102 |
+
// before Twig 1.26
|
103 |
$twig->getExtension('core')->setEscaper('csv', 'csv_escaper');
|
104 |
|
105 |
When called by Twig, the callable receives the Twig environment instance, the
|
library/twig/twig/doc/filters/number_format.rst
CHANGED
@@ -30,6 +30,9 @@ These defaults can be easily changed through the core extension:
|
|
30 |
.. code-block:: php
|
31 |
|
32 |
$twig = new Twig_Environment($loader);
|
|
|
|
|
|
|
33 |
$twig->getExtension('core')->setNumberFormat(3, '.', ',');
|
34 |
|
35 |
The defaults set for ``number_format`` can be over-ridden upon each call using the
|
30 |
.. code-block:: php
|
31 |
|
32 |
$twig = new Twig_Environment($loader);
|
33 |
+
$twig->getExtension('Twig_Extension_Core')->setNumberFormat(3, '.', ',');
|
34 |
+
|
35 |
+
// before Twig 1.26
|
36 |
$twig->getExtension('core')->setNumberFormat(3, '.', ',');
|
37 |
|
38 |
The defaults set for ``number_format`` can be over-ridden upon each call using the
|
library/twig/twig/doc/functions/block.rst
CHANGED
@@ -1,6 +1,12 @@
|
|
1 |
``block``
|
2 |
=========
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
When a template uses inheritance and if you want to print a block multiple
|
5 |
times, use the ``block`` function:
|
6 |
|
@@ -12,4 +18,24 @@ times, use the ``block`` function:
|
|
12 |
|
13 |
{% block body %}{% endblock %}
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
.. seealso:: :doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`
|
1 |
``block``
|
2 |
=========
|
3 |
|
4 |
+
.. versionadded: 1.28
|
5 |
+
Using ``block`` with the ``defined`` test was added in Twig 1.28.
|
6 |
+
|
7 |
+
.. versionadded: 1.28
|
8 |
+
Support for the template argument was added in Twig 1.28.
|
9 |
+
|
10 |
When a template uses inheritance and if you want to print a block multiple
|
11 |
times, use the ``block`` function:
|
12 |
|
18 |
|
19 |
{% block body %}{% endblock %}
|
20 |
|
21 |
+
The ``block`` function can also be used to display one block of another
|
22 |
+
template:
|
23 |
+
|
24 |
+
.. code-block:: jinja
|
25 |
+
|
26 |
+
{{ block("title", "common_blocks.twig") }}
|
27 |
+
|
28 |
+
Use the ``defined`` test to check if a block exists in the context of the
|
29 |
+
current template:
|
30 |
+
|
31 |
+
.. code-block:: jinja
|
32 |
+
|
33 |
+
{% if block("footer") is defined %}
|
34 |
+
...
|
35 |
+
{% endif %}
|
36 |
+
|
37 |
+
{% if block("footer", "common_blocks.twig") is defined %}
|
38 |
+
...
|
39 |
+
{% endif %}
|
40 |
+
|
41 |
.. seealso:: :doc:`extends<../tags/extends>`, :doc:`parent<../functions/parent>`
|
library/twig/twig/doc/functions/constant.rst
CHANGED
@@ -4,6 +4,9 @@
|
|
4 |
.. versionadded: 1.12.1
|
5 |
constant now accepts object instances as the second argument.
|
6 |
|
|
|
|
|
|
|
7 |
``constant`` returns the constant value for a given string:
|
8 |
|
9 |
.. code-block:: jinja
|
@@ -16,3 +19,11 @@ As of 1.12.1 you can read constants from object instances as well:
|
|
16 |
.. code-block:: jinja
|
17 |
|
18 |
{{ constant('RSS', date) }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
.. versionadded: 1.12.1
|
5 |
constant now accepts object instances as the second argument.
|
6 |
|
7 |
+
.. versionadded: 1.28
|
8 |
+
Using ``constant`` with the ``defined`` test was added in Twig 1.28.
|
9 |
+
|
10 |
``constant`` returns the constant value for a given string:
|
11 |
|
12 |
.. code-block:: jinja
|
19 |
.. code-block:: jinja
|
20 |
|
21 |
{{ constant('RSS', date) }}
|
22 |
+
|
23 |
+
Use the ``defined`` test to check if a constant is defined:
|
24 |
+
|
25 |
+
.. code-block:: jinja
|
26 |
+
|
27 |
+
{% if constant('SOME_CONST') is defined %}
|
28 |
+
...
|
29 |
+
{% endif %}
|
library/twig/twig/doc/functions/date.rst
CHANGED
@@ -41,6 +41,9 @@ If no argument is passed, the function returns the current date:
|
|
41 |
.. code-block:: php
|
42 |
|
43 |
$twig = new Twig_Environment($loader);
|
|
|
|
|
|
|
44 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
45 |
|
46 |
Arguments
|
41 |
.. code-block:: php
|
42 |
|
43 |
$twig = new Twig_Environment($loader);
|
44 |
+
$twig->getExtension('Twig_Extension_Core')->setTimezone('Europe/Paris');
|
45 |
+
|
46 |
+
// before Twig 1.26
|
47 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
48 |
|
49 |
Arguments
|
library/twig/twig/doc/functions/include.rst
CHANGED
@@ -37,14 +37,18 @@ You can disable access to the context by setting ``with_context`` to
|
|
37 |
{# no variables will be accessible #}
|
38 |
{{ include('template.html', with_context = false) }}
|
39 |
|
40 |
-
And if the expression evaluates to a ``Twig_Template``
|
41 |
-
directly::
|
42 |
|
43 |
// {{ include(template) }}
|
44 |
|
|
|
45 |
$template = $twig->loadTemplate('some_template.twig');
|
46 |
|
47 |
-
|
|
|
|
|
|
|
48 |
|
49 |
When you set the ``ignore_missing`` flag, Twig will return an empty string if
|
50 |
the template does not exist:
|
37 |
{# no variables will be accessible #}
|
38 |
{{ include('template.html', with_context = false) }}
|
39 |
|
40 |
+
And if the expression evaluates to a ``Twig_Template`` or a
|
41 |
+
``Twig_TemplateWrapper`` instance, Twig will use it directly::
|
42 |
|
43 |
// {{ include(template) }}
|
44 |
|
45 |
+
// deprecated as of Twig 1.28
|
46 |
$template = $twig->loadTemplate('some_template.twig');
|
47 |
|
48 |
+
// as of Twig 1.28
|
49 |
+
$template = $twig->load('some_template.twig');
|
50 |
+
|
51 |
+
$twig->display('template.twig', array('template' => $template));
|
52 |
|
53 |
When you set the ``ignore_missing`` flag, Twig will return an empty string if
|
54 |
the template does not exist:
|
library/twig/twig/doc/internals.rst
CHANGED
@@ -44,7 +44,11 @@ an instance of ``Twig_Token``, and the stream is an instance of
|
|
44 |
You can manually convert a source code into a token stream by calling the
|
45 |
``tokenize()`` method of an environment::
|
46 |
|
47 |
-
$stream = $twig->tokenize($source, $identifier);
|
|
|
|
|
|
|
|
|
48 |
|
49 |
As the stream has a ``__toString()`` method, you can have a textual
|
50 |
representation of it by echoing the object::
|
44 |
You can manually convert a source code into a token stream by calling the
|
45 |
``tokenize()`` method of an environment::
|
46 |
|
47 |
+
$stream = $twig->tokenize(new Twig_Source($source, $identifier));
|
48 |
+
|
49 |
+
.. versionadded:: 1.27
|
50 |
+
``Twig_Source`` was introduced in version 1.27, pass the source and the
|
51 |
+
identifier directly on previous versions.
|
52 |
|
53 |
As the stream has a ``__toString()`` method, you can have a textual
|
54 |
representation of it by echoing the object::
|
library/twig/twig/doc/recipes.rst
CHANGED
@@ -306,7 +306,7 @@ saving it. If the template code is stored in a `$template` variable, here is
|
|
306 |
how you can do it::
|
307 |
|
308 |
try {
|
309 |
-
$twig->parse($twig->tokenize($template));
|
310 |
|
311 |
// the $template is valid
|
312 |
} catch (Twig_Error_Syntax $e) {
|
@@ -318,7 +318,7 @@ If you iterate over a set of files, you can pass the filename to the
|
|
318 |
|
319 |
foreach ($files as $file) {
|
320 |
try {
|
321 |
-
$twig->parse($twig->tokenize($template, $file));
|
322 |
|
323 |
// the $template is valid
|
324 |
} catch (Twig_Error_Syntax $e) {
|
@@ -326,6 +326,10 @@ If you iterate over a set of files, you can pass the filename to the
|
|
326 |
}
|
327 |
}
|
328 |
|
|
|
|
|
|
|
|
|
329 |
.. note::
|
330 |
|
331 |
This method won't catch any sandbox policy violations because the policy
|
@@ -413,7 +417,7 @@ We have created a simple ``templates`` table that hosts two templates:
|
|
413 |
|
414 |
Now, let's define a loader able to use this database::
|
415 |
|
416 |
-
class DatabaseTwigLoader implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
417 |
{
|
418 |
protected $dbh;
|
419 |
|
@@ -431,6 +435,16 @@ Now, let's define a loader able to use this database::
|
|
431 |
return $source;
|
432 |
}
|
433 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
434 |
// Twig_ExistsLoaderInterface as of Twig 1.11
|
435 |
public function exists($name)
|
436 |
{
|
@@ -515,4 +529,40 @@ From PHP, it's also possible to load a template stored in a string via
|
|
515 |
|
516 |
Never use the ``Twig_Loader_String`` loader, which has severe limitations.
|
517 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
.. _callback: http://www.php.net/manual/en/function.is-callable.php
|
306 |
how you can do it::
|
307 |
|
308 |
try {
|
309 |
+
$twig->parse($twig->tokenize(new Twig_Source($template)));
|
310 |
|
311 |
// the $template is valid
|
312 |
} catch (Twig_Error_Syntax $e) {
|
318 |
|
319 |
foreach ($files as $file) {
|
320 |
try {
|
321 |
+
$twig->parse($twig->tokenize(new Twig_Source($template, $file->getFilename(), $file)));
|
322 |
|
323 |
// the $template is valid
|
324 |
} catch (Twig_Error_Syntax $e) {
|
326 |
}
|
327 |
}
|
328 |
|
329 |
+
.. versionadded:: 1.27
|
330 |
+
``Twig_Source`` was introduced in version 1.27, pass the source and the
|
331 |
+
identifier directly on previous versions.
|
332 |
+
|
333 |
.. note::
|
334 |
|
335 |
This method won't catch any sandbox policy violations because the policy
|
417 |
|
418 |
Now, let's define a loader able to use this database::
|
419 |
|
420 |
+
class DatabaseTwigLoader implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
421 |
{
|
422 |
protected $dbh;
|
423 |
|
435 |
return $source;
|
436 |
}
|
437 |
|
438 |
+
// Twig_SourceContextLoaderInterface as of Twig 1.27
|
439 |
+
public function getSourceContext($name)
|
440 |
+
{
|
441 |
+
if (false === $source = $this->getValue('source', $name)) {
|
442 |
+
throw new Twig_Error_Loader(sprintf('Template "%s" does not exist.', $name));
|
443 |
+
}
|
444 |
+
|
445 |
+
return new Twig_Source($source, $name);
|
446 |
+
}
|
447 |
+
|
448 |
// Twig_ExistsLoaderInterface as of Twig 1.11
|
449 |
public function exists($name)
|
450 |
{
|
529 |
|
530 |
Never use the ``Twig_Loader_String`` loader, which has severe limitations.
|
531 |
|
532 |
+
Using Twig and AngularJS in the same Templates
|
533 |
+
----------------------------------------------
|
534 |
+
|
535 |
+
Mixing different template syntaxes in the same file is not a recommended
|
536 |
+
practice as both AngularJS and Twig use the same delimiters in their syntax:
|
537 |
+
``{{`` and ``}}``.
|
538 |
+
|
539 |
+
Still, if you want to use AngularJS and Twig in the same template, there are
|
540 |
+
two ways to make it work depending on the amount of AngularJS you need to
|
541 |
+
include in your templates:
|
542 |
+
|
543 |
+
* Escaping the AngularJS delimiters by wrapping AngularJS sections with the
|
544 |
+
``{% verbatim %}`` tag or by escaping each delimiter via ``{{ '{{' }}`` and
|
545 |
+
``{{ '}}' }}``;
|
546 |
+
|
547 |
+
* Changing the delimiters of one of the template engines (depending on which
|
548 |
+
engine you introduced last):
|
549 |
+
|
550 |
+
* For AngularJS, change the interpolation tags using the
|
551 |
+
``interpolateProvider`` service, for instance at the module initialization
|
552 |
+
time:
|
553 |
+
|
554 |
+
..code-block:: javascript
|
555 |
+
|
556 |
+
angular.module('myApp', []).config(function($interpolateProvider) {
|
557 |
+
$interpolateProvider.startSymbol('{[').endSymbol(']}');
|
558 |
+
});
|
559 |
+
|
560 |
+
* For Twig, change the delimiters via the ``tag_variable`` Lexer option:
|
561 |
+
|
562 |
+
..code-block:: php
|
563 |
+
|
564 |
+
$env->setLexer(new Twig_Lexer($env, array(
|
565 |
+
'tag_variable' => array('{[', ']}'),
|
566 |
+
)));
|
567 |
+
|
568 |
.. _callback: http://www.php.net/manual/en/function.is-callable.php
|
library/twig/twig/doc/tags/autoescape.rst
CHANGED
@@ -6,8 +6,6 @@ template to be escaped or not by using the ``autoescape`` tag:
|
|
6 |
|
7 |
.. code-block:: jinja
|
8 |
|
9 |
-
{# The following syntax works as of Twig 1.8 -- see the note below for previous versions #}
|
10 |
-
|
11 |
{% autoescape %}
|
12 |
Everything will be automatically escaped in this block
|
13 |
using the HTML strategy
|
6 |
|
7 |
.. code-block:: jinja
|
8 |
|
|
|
|
|
9 |
{% autoescape %}
|
10 |
Everything will be automatically escaped in this block
|
11 |
using the HTML strategy
|
library/twig/twig/doc/tags/embed.rst
CHANGED
@@ -170,9 +170,9 @@ The ``embed`` tag takes the exact same arguments as the ``include`` tag:
|
|
170 |
.. warning::
|
171 |
|
172 |
As embedded templates do not have "names", auto-escaping strategies based
|
173 |
-
on the template
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
|
178 |
.. seealso:: :doc:`include<../tags/include>`
|
170 |
.. warning::
|
171 |
|
172 |
As embedded templates do not have "names", auto-escaping strategies based
|
173 |
+
on the template name won't work as expected if you change the context (for
|
174 |
+
instance, if you embed a CSS/JavaScript template into an HTML one). In that
|
175 |
+
case, explicitly set the default auto-escaping strategy with the
|
176 |
+
``autoescape`` tag.
|
177 |
|
178 |
.. seealso:: :doc:`include<../tags/include>`
|
library/twig/twig/doc/tags/extends.rst
CHANGED
@@ -153,13 +153,17 @@ Twig supports dynamic inheritance by using a variable as the base template:
|
|
153 |
|
154 |
{% extends some_var %}
|
155 |
|
156 |
-
If the variable evaluates to a ``Twig_Template``
|
157 |
-
the parent template::
|
158 |
|
159 |
// {% extends layout %}
|
160 |
|
|
|
161 |
$layout = $twig->loadTemplate('some_layout_template.twig');
|
162 |
|
|
|
|
|
|
|
163 |
$twig->display('template.twig', array('layout' => $layout));
|
164 |
|
165 |
.. versionadded:: 1.2
|
153 |
|
154 |
{% extends some_var %}
|
155 |
|
156 |
+
If the variable evaluates to a ``Twig_Template`` or a ``Twig_TemplateWraper``
|
157 |
+
instance, Twig will use it as the parent template::
|
158 |
|
159 |
// {% extends layout %}
|
160 |
|
161 |
+
// deprecated as of Twig 1.28
|
162 |
$layout = $twig->loadTemplate('some_layout_template.twig');
|
163 |
|
164 |
+
// as of Twig 1.28
|
165 |
+
$layout = $twig->load('some_layout_template.twig');
|
166 |
+
|
167 |
$twig->display('template.twig', array('layout' => $layout));
|
168 |
|
169 |
.. versionadded:: 1.2
|
library/twig/twig/doc/tags/include.rst
CHANGED
@@ -50,14 +50,18 @@ The template name can be any valid Twig expression:
|
|
50 |
{% include some_var %}
|
51 |
{% include ajax ? 'ajax.html' : 'not_ajax.html' %}
|
52 |
|
53 |
-
And if the expression evaluates to a ``Twig_Template``
|
54 |
-
directly::
|
55 |
|
56 |
// {% include template %}
|
57 |
|
|
|
58 |
$template = $twig->loadTemplate('some_template.twig');
|
59 |
|
60 |
-
|
|
|
|
|
|
|
61 |
|
62 |
.. versionadded:: 1.2
|
63 |
The ``ignore missing`` feature has been added in Twig 1.2.
|
50 |
{% include some_var %}
|
51 |
{% include ajax ? 'ajax.html' : 'not_ajax.html' %}
|
52 |
|
53 |
+
And if the expression evaluates to a ``Twig_Template`` or a
|
54 |
+
``Twig_TemplateWrapper`` instance, Twig will use it directly::
|
55 |
|
56 |
// {% include template %}
|
57 |
|
58 |
+
// deprecated as of Twig 1.28
|
59 |
$template = $twig->loadTemplate('some_template.twig');
|
60 |
|
61 |
+
// as of Twig 1.28
|
62 |
+
$template = $twig->load('some_template.twig');
|
63 |
+
|
64 |
+
$twig->display('template.twig', array('template' => $template));
|
65 |
|
66 |
.. versionadded:: 1.2
|
67 |
The ``ignore missing`` feature has been added in Twig 1.2.
|
library/twig/twig/doc/tags/index.rst
CHANGED
@@ -22,3 +22,4 @@ Tags
|
|
22 |
spaceless
|
23 |
use
|
24 |
verbatim
|
|
22 |
spaceless
|
23 |
use
|
24 |
verbatim
|
25 |
+
with
|
library/twig/twig/doc/tags/with.rst
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
``with``
|
2 |
+
========
|
3 |
+
|
4 |
+
.. versionadded:: 1.28
|
5 |
+
The ``with`` tag was added in Twig 1.28.
|
6 |
+
|
7 |
+
Use the ``with`` tag to create a new inner scope. Variables set within this
|
8 |
+
scope are not visible outside of the scope:
|
9 |
+
|
10 |
+
.. code-block:: jinja
|
11 |
+
|
12 |
+
{% with %}
|
13 |
+
{% set foo = 42 %}
|
14 |
+
{{ foo }} foo is 42 here
|
15 |
+
{% endwith %}
|
16 |
+
foo is not visible here any longer
|
17 |
+
|
18 |
+
Instead of defining variables at the beginning of the scope, you can pass a
|
19 |
+
hash of variables you want to define in the ``with`` tag; the previous example
|
20 |
+
is equivalent to the following one:
|
21 |
+
|
22 |
+
.. code-block:: jinja
|
23 |
+
|
24 |
+
{% with { foo: 42 } %}
|
25 |
+
{{ foo }} foo is 42 here
|
26 |
+
{% endwith %}
|
27 |
+
foo is not visible here any longer
|
28 |
+
|
29 |
+
{# it works with any expression that resolves to a hash #}
|
30 |
+
{% set vars = { foo: 42 } %}
|
31 |
+
{% with vars %}
|
32 |
+
...
|
33 |
+
{% endwith %}
|
34 |
+
|
35 |
+
By default, the inner scope has access to the outer scope context; you can
|
36 |
+
disable this behavior by appending the ``only`` keyword:
|
37 |
+
|
38 |
+
.. code-block:: jinja
|
39 |
+
|
40 |
+
{% set bar = 'bar' %}
|
41 |
+
{% with { foo: 42 } only %}
|
42 |
+
{# only foo is defined #}
|
43 |
+
{# bar is not defined #}
|
44 |
+
{% endwith %}
|
library/twig/twig/doc/templates.rst
CHANGED
@@ -424,10 +424,8 @@ everything by default.
|
|
424 |
|
425 |
Twig supports both, automatic escaping is enabled by default.
|
426 |
|
427 |
-
|
428 |
-
|
429 |
-
Automatic escaping is only supported if the *escaper* extension has been
|
430 |
-
enabled (which is the default).
|
431 |
|
432 |
Working with Manual Escaping
|
433 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
424 |
|
425 |
Twig supports both, automatic escaping is enabled by default.
|
426 |
|
427 |
+
The automatic escaping strategy can be configured via the
|
428 |
+
:ref:`autoescape<environment_options>` option and defaults to ``html``.
|
|
|
|
|
429 |
|
430 |
Working with Manual Escaping
|
431 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
library/twig/twig/doc/tests/empty.rst
CHANGED
@@ -6,7 +6,6 @@ hash, exactly ``false``, or exactly ``null``:
|
|
6 |
|
7 |
.. code-block:: jinja
|
8 |
|
9 |
-
{# evaluates to true if the foo variable is null, false, an empty array, or the empty string #}
|
10 |
{% if foo is empty %}
|
11 |
...
|
12 |
{% endif %}
|
6 |
|
7 |
.. code-block:: jinja
|
8 |
|
|
|
9 |
{% if foo is empty %}
|
10 |
...
|
11 |
{% endif %}
|
library/twig/twig/ext/twig/php_twig.h
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
-
#define PHP_TWIG_VERSION "1.
|
19 |
|
20 |
#include "php.h"
|
21 |
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
+
#define PHP_TWIG_VERSION "1.28.2"
|
19 |
|
20 |
#include "php.h"
|
21 |
|
library/twig/twig/ext/twig/twig.c
CHANGED
@@ -144,7 +144,7 @@ static zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
|
144 |
|
145 |
if (!retval) {
|
146 |
if (!EG(exception)) {
|
147 |
-
zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
|
148 |
}
|
149 |
return NULL;
|
150 |
}
|
@@ -167,7 +167,7 @@ static int TWIG_ISSET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
|
167 |
|
168 |
if (!retval) {
|
169 |
if (!EG(exception)) {
|
170 |
-
zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
|
171 |
}
|
172 |
return 0;
|
173 |
}
|
@@ -811,15 +811,15 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
811 |
}
|
812 |
*/
|
813 |
if (TWIG_INSTANCE_OF(object, zend_ce_arrayaccess TSRMLS_CC)) {
|
814 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" in object with ArrayAccess of class \"%s\" does not exist", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
815 |
} else if (Z_TYPE_P(object) == IS_OBJECT) {
|
816 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to access a key \"%s\" on an object of class \"%s\" that does not implement ArrayAccess interface", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
817 |
} else if (Z_TYPE_P(object) == IS_ARRAY) {
|
818 |
if (0 == zend_hash_num_elements(Z_ARRVAL_P(object))) {
|
819 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" does not exist as the array is empty", item);
|
820 |
} else {
|
821 |
char *array_keys = TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC);
|
822 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist", item, array_keys);
|
823 |
efree(array_keys);
|
824 |
}
|
825 |
} else {
|
@@ -829,15 +829,15 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
829 |
convert_to_string(object);
|
830 |
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
831 |
(strcmp("array", type) == 0)
|
832 |
-
? "Impossible to access a key (\"%s\") on a %s variable"
|
833 |
-
: "Impossible to access an attribute (\"%s\") on a %s variable",
|
834 |
item, type_name);
|
835 |
} else {
|
836 |
convert_to_string(object);
|
837 |
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
838 |
(strcmp("array", type) == 0)
|
839 |
-
? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
|
840 |
-
: "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
|
841 |
item, type_name, Z_STRVAL_P(object));
|
842 |
}
|
843 |
zval_ptr_dtor(&object);
|
@@ -883,11 +883,11 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
883 |
if (Z_TYPE_P(object) == IS_NULL) {
|
884 |
convert_to_string_ex(&object);
|
885 |
|
886 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable", item, type_name);
|
887 |
} else {
|
888 |
convert_to_string_ex(&object);
|
889 |
|
890 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));
|
891 |
}
|
892 |
|
893 |
zval_ptr_dtor(&object);
|
@@ -916,8 +916,8 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
916 |
return true;
|
917 |
}
|
918 |
|
919 |
-
if ($this->env->hasExtension('
|
920 |
-
$this->env->getExtension('
|
921 |
}
|
922 |
|
923 |
return $object->$item;
|
@@ -935,8 +935,8 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
935 |
efree(item);
|
936 |
RETURN_TRUE;
|
937 |
}
|
938 |
-
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "
|
939 |
-
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "
|
940 |
}
|
941 |
if (EG(exception)) {
|
942 |
efree(item);
|
@@ -1020,7 +1020,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1020 |
return null;
|
1021 |
}
|
1022 |
|
1023 |
-
throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
|
1024 |
}
|
1025 |
|
1026 |
if ($isDefinedTest) {
|
@@ -1040,7 +1040,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1040 |
efree(item);
|
1041 |
return;
|
1042 |
}
|
1043 |
-
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Neither the property \"%s\" nor one of the methods \"%s()\", \"get%s()\"/\"is%s()\" or \"__call()\" exist and have public access in class \"%s\"", item, item, item, item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
1044 |
efree(item);
|
1045 |
return;
|
1046 |
}
|
@@ -1052,14 +1052,14 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1052 |
RETURN_TRUE;
|
1053 |
}
|
1054 |
/*
|
1055 |
-
if ($this->env->hasExtension('
|
1056 |
-
$this->env->getExtension('
|
1057 |
}
|
1058 |
*/
|
1059 |
MAKE_STD_ZVAL(zmethod);
|
1060 |
ZVAL_STRING(zmethod, method, 1);
|
1061 |
-
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "
|
1062 |
-
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "
|
1063 |
}
|
1064 |
zval_ptr_dtor(&zmethod);
|
1065 |
if (EG(exception)) {
|
144 |
|
145 |
if (!retval) {
|
146 |
if (!EG(exception)) {
|
147 |
+
zend_error(E_ERROR, "Undefined offset for object of type %s used as array.", ce->name);
|
148 |
}
|
149 |
return NULL;
|
150 |
}
|
167 |
|
168 |
if (!retval) {
|
169 |
if (!EG(exception)) {
|
170 |
+
zend_error(E_ERROR, "Undefined offset for object of type %s used as array.", ce->name);
|
171 |
}
|
172 |
return 0;
|
173 |
}
|
811 |
}
|
812 |
*/
|
813 |
if (TWIG_INSTANCE_OF(object, zend_ce_arrayaccess TSRMLS_CC)) {
|
814 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" in object with ArrayAccess of class \"%s\" does not exist.", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
815 |
} else if (Z_TYPE_P(object) == IS_OBJECT) {
|
816 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to access a key \"%s\" on an object of class \"%s\" that does not implement ArrayAccess interface.", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
817 |
} else if (Z_TYPE_P(object) == IS_ARRAY) {
|
818 |
if (0 == zend_hash_num_elements(Z_ARRVAL_P(object))) {
|
819 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" does not exist as the array is empty.", item);
|
820 |
} else {
|
821 |
char *array_keys = TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC);
|
822 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist.", item, array_keys);
|
823 |
efree(array_keys);
|
824 |
}
|
825 |
} else {
|
829 |
convert_to_string(object);
|
830 |
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
831 |
(strcmp("array", type) == 0)
|
832 |
+
? "Impossible to access a key (\"%s\") on a %s variable."
|
833 |
+
: "Impossible to access an attribute (\"%s\") on a %s variable.",
|
834 |
item, type_name);
|
835 |
} else {
|
836 |
convert_to_string(object);
|
837 |
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
838 |
(strcmp("array", type) == 0)
|
839 |
+
? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")."
|
840 |
+
: "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\").",
|
841 |
item, type_name, Z_STRVAL_P(object));
|
842 |
}
|
843 |
zval_ptr_dtor(&object);
|
883 |
if (Z_TYPE_P(object) == IS_NULL) {
|
884 |
convert_to_string_ex(&object);
|
885 |
|
886 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable.", item, type_name);
|
887 |
} else {
|
888 |
convert_to_string_ex(&object);
|
889 |
|
890 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\").", item, type_name, Z_STRVAL_P(object));
|
891 |
}
|
892 |
|
893 |
zval_ptr_dtor(&object);
|
916 |
return true;
|
917 |
}
|
918 |
|
919 |
+
if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
|
920 |
+
$this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item);
|
921 |
}
|
922 |
|
923 |
return $object->$item;
|
935 |
efree(item);
|
936 |
RETURN_TRUE;
|
937 |
}
|
938 |
+
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "Twig_Extension_Sandbox" TSRMLS_CC)) {
|
939 |
+
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "Twig_Extension_Sandbox" TSRMLS_CC), "checkPropertyAllowed", object, zitem TSRMLS_CC);
|
940 |
}
|
941 |
if (EG(exception)) {
|
942 |
efree(item);
|
1020 |
return null;
|
1021 |
}
|
1022 |
|
1023 |
+
throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist.', $item, get_class($object)), -1, $this->getTemplateName());
|
1024 |
}
|
1025 |
|
1026 |
if ($isDefinedTest) {
|
1040 |
efree(item);
|
1041 |
return;
|
1042 |
}
|
1043 |
+
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Neither the property \"%s\" nor one of the methods \"%s()\", \"get%s()\"/\"is%s()\" or \"__call()\" exist and have public access in class \"%s\".", item, item, item, item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
1044 |
efree(item);
|
1045 |
return;
|
1046 |
}
|
1052 |
RETURN_TRUE;
|
1053 |
}
|
1054 |
/*
|
1055 |
+
if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
|
1056 |
+
$this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method);
|
1057 |
}
|
1058 |
*/
|
1059 |
MAKE_STD_ZVAL(zmethod);
|
1060 |
ZVAL_STRING(zmethod, method, 1);
|
1061 |
+
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "Twig_Extension_Sandbox" TSRMLS_CC)) {
|
1062 |
+
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "Twig_Extension_Sandbox" TSRMLS_CC), "checkMethodAllowed", object, zmethod TSRMLS_CC);
|
1063 |
}
|
1064 |
zval_ptr_dtor(&zmethod);
|
1065 |
if (EG(exception)) {
|
library/twig/twig/lib/Twig/BaseNodeVisitor.php
CHANGED
@@ -43,9 +43,6 @@ abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
|
|
43 |
/**
|
44 |
* Called before child nodes are visited.
|
45 |
*
|
46 |
-
* @param Twig_Node $node The node to visit
|
47 |
-
* @param Twig_Environment $env The Twig environment instance
|
48 |
-
*
|
49 |
* @return Twig_Node The modified node
|
50 |
*/
|
51 |
abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env);
|
@@ -53,9 +50,6 @@ abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
|
|
53 |
/**
|
54 |
* Called after child nodes are visited.
|
55 |
*
|
56 |
-
* @param Twig_Node $node The node to visit
|
57 |
-
* @param Twig_Environment $env The Twig environment instance
|
58 |
-
*
|
59 |
* @return Twig_Node|false The modified node or false if the node must be removed
|
60 |
*/
|
61 |
abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env);
|
43 |
/**
|
44 |
* Called before child nodes are visited.
|
45 |
*
|
|
|
|
|
|
|
46 |
* @return Twig_Node The modified node
|
47 |
*/
|
48 |
abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env);
|
50 |
/**
|
51 |
* Called after child nodes are visited.
|
52 |
*
|
|
|
|
|
|
|
53 |
* @return Twig_Node|false The modified node or false if the node must be removed
|
54 |
*/
|
55 |
abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env);
|
library/twig/twig/lib/Twig/Compiler.php
CHANGED
@@ -26,11 +26,6 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
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;
|
@@ -49,7 +44,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
49 |
/**
|
50 |
* Returns the environment instance related to this compiler.
|
51 |
*
|
52 |
-
* @return Twig_Environment
|
53 |
*/
|
54 |
public function getEnvironment()
|
55 |
{
|
@@ -72,7 +67,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
72 |
* @param Twig_NodeInterface $node The node to compile
|
73 |
* @param int $indentation The current indentation
|
74 |
*
|
75 |
-
* @return
|
76 |
*/
|
77 |
public function compile(Twig_NodeInterface $node, $indentation = 0)
|
78 |
{
|
@@ -85,10 +80,8 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
85 |
$this->indentation = $indentation;
|
86 |
|
87 |
if ($node instanceof Twig_Node_Module) {
|
88 |
-
$node->setFilename($node->getAttribute('filename'));
|
89 |
-
|
90 |
// to be removed in 2.0
|
91 |
-
$this->filename = $node->
|
92 |
}
|
93 |
|
94 |
$node->compile($this);
|
@@ -99,7 +92,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
99 |
public function subcompile(Twig_NodeInterface $node, $raw = true)
|
100 |
{
|
101 |
if (false === $raw) {
|
102 |
-
$this->
|
103 |
}
|
104 |
|
105 |
$node->compile($this);
|
@@ -112,7 +105,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
112 |
*
|
113 |
* @param string $string The string
|
114 |
*
|
115 |
-
* @return
|
116 |
*/
|
117 |
public function raw($string)
|
118 |
{
|
@@ -124,14 +117,13 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
124 |
/**
|
125 |
* Writes a string to the compiled code by adding indentation.
|
126 |
*
|
127 |
-
* @return
|
128 |
*/
|
129 |
public function write()
|
130 |
{
|
131 |
$strings = func_get_args();
|
132 |
foreach ($strings as $string) {
|
133 |
-
$this->
|
134 |
-
$this->source .= $string;
|
135 |
}
|
136 |
|
137 |
return $this;
|
@@ -140,10 +132,14 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
140 |
/**
|
141 |
* Appends an indentation to the current PHP code after compilation.
|
142 |
*
|
143 |
-
* @return
|
|
|
|
|
144 |
*/
|
145 |
public function addIndentation()
|
146 |
{
|
|
|
|
|
147 |
$this->source .= str_repeat(' ', $this->indentation * 4);
|
148 |
|
149 |
return $this;
|
@@ -154,7 +150,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
154 |
*
|
155 |
* @param string $value The string
|
156 |
*
|
157 |
-
* @return
|
158 |
*/
|
159 |
public function string($value)
|
160 |
{
|
@@ -168,7 +164,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
168 |
*
|
169 |
* @param mixed $value The value to convert
|
170 |
*
|
171 |
-
* @return
|
172 |
*/
|
173 |
public function repr($value)
|
174 |
{
|
@@ -209,14 +205,12 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
209 |
/**
|
210 |
* Adds debugging information.
|
211 |
*
|
212 |
-
* @
|
213 |
-
*
|
214 |
-
* @return Twig_Compiler The current compiler instance
|
215 |
*/
|
216 |
public function addDebugInfo(Twig_NodeInterface $node)
|
217 |
{
|
218 |
-
if ($node->
|
219 |
-
$this->write(sprintf("// line %d\n", $node->
|
220 |
|
221 |
// when mbstring.func_overload is set to 2
|
222 |
// mb_substr_count() replaces substr_count()
|
@@ -228,9 +222,9 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
228 |
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
229 |
}
|
230 |
$this->sourceOffset = strlen($this->source);
|
231 |
-
$this->debugInfo[$this->sourceLine] = $node->
|
232 |
|
233 |
-
$this->lastLine = $node->
|
234 |
}
|
235 |
|
236 |
return $this;
|
@@ -248,7 +242,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
248 |
*
|
249 |
* @param int $step The number of indentation to add
|
250 |
*
|
251 |
-
* @return
|
252 |
*/
|
253 |
public function indent($step = 1)
|
254 |
{
|
@@ -262,7 +256,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
262 |
*
|
263 |
* @param int $step The number of indentation to remove
|
264 |
*
|
265 |
-
* @return
|
266 |
*
|
267 |
* @throws LogicException When trying to outdent too much so the indentation would become negative
|
268 |
*/
|
@@ -270,7 +264,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
270 |
{
|
271 |
// can't outdent by more steps than the current indentation level
|
272 |
if ($this->indentation < $step) {
|
273 |
-
throw new LogicException('Unable to call outdent() as the indentation would become negative');
|
274 |
}
|
275 |
|
276 |
$this->indentation -= $step;
|
26 |
protected $sourceLine;
|
27 |
protected $filename;
|
28 |
|
|
|
|
|
|
|
|
|
|
|
29 |
public function __construct(Twig_Environment $env)
|
30 |
{
|
31 |
$this->env = $env;
|
44 |
/**
|
45 |
* Returns the environment instance related to this compiler.
|
46 |
*
|
47 |
+
* @return Twig_Environment
|
48 |
*/
|
49 |
public function getEnvironment()
|
50 |
{
|
67 |
* @param Twig_NodeInterface $node The node to compile
|
68 |
* @param int $indentation The current indentation
|
69 |
*
|
70 |
+
* @return $this
|
71 |
*/
|
72 |
public function compile(Twig_NodeInterface $node, $indentation = 0)
|
73 |
{
|
80 |
$this->indentation = $indentation;
|
81 |
|
82 |
if ($node instanceof Twig_Node_Module) {
|
|
|
|
|
83 |
// to be removed in 2.0
|
84 |
+
$this->filename = $node->getTemplateName();
|
85 |
}
|
86 |
|
87 |
$node->compile($this);
|
92 |
public function subcompile(Twig_NodeInterface $node, $raw = true)
|
93 |
{
|
94 |
if (false === $raw) {
|
95 |
+
$this->source .= str_repeat(' ', $this->indentation * 4);
|
96 |
}
|
97 |
|
98 |
$node->compile($this);
|
105 |
*
|
106 |
* @param string $string The string
|
107 |
*
|
108 |
+
* @return $this
|
109 |
*/
|
110 |
public function raw($string)
|
111 |
{
|
117 |
/**
|
118 |
* Writes a string to the compiled code by adding indentation.
|
119 |
*
|
120 |
+
* @return $this
|
121 |
*/
|
122 |
public function write()
|
123 |
{
|
124 |
$strings = func_get_args();
|
125 |
foreach ($strings as $string) {
|
126 |
+
$this->source .= str_repeat(' ', $this->indentation * 4).$string;
|
|
|
127 |
}
|
128 |
|
129 |
return $this;
|
132 |
/**
|
133 |
* Appends an indentation to the current PHP code after compilation.
|
134 |
*
|
135 |
+
* @return $this
|
136 |
+
*
|
137 |
+
* @deprecated since 1.27 (to be removed in 2.0).
|
138 |
*/
|
139 |
public function addIndentation()
|
140 |
{
|
141 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED);
|
142 |
+
|
143 |
$this->source .= str_repeat(' ', $this->indentation * 4);
|
144 |
|
145 |
return $this;
|
150 |
*
|
151 |
* @param string $value The string
|
152 |
*
|
153 |
+
* @return $this
|
154 |
*/
|
155 |
public function string($value)
|
156 |
{
|
164 |
*
|
165 |
* @param mixed $value The value to convert
|
166 |
*
|
167 |
+
* @return $this
|
168 |
*/
|
169 |
public function repr($value)
|
170 |
{
|
205 |
/**
|
206 |
* Adds debugging information.
|
207 |
*
|
208 |
+
* @return $this
|
|
|
|
|
209 |
*/
|
210 |
public function addDebugInfo(Twig_NodeInterface $node)
|
211 |
{
|
212 |
+
if ($node->getTemplateLine() != $this->lastLine) {
|
213 |
+
$this->write(sprintf("// line %d\n", $node->getTemplateLine()));
|
214 |
|
215 |
// when mbstring.func_overload is set to 2
|
216 |
// mb_substr_count() replaces substr_count()
|
222 |
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
223 |
}
|
224 |
$this->sourceOffset = strlen($this->source);
|
225 |
+
$this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
|
226 |
|
227 |
+
$this->lastLine = $node->getTemplateLine();
|
228 |
}
|
229 |
|
230 |
return $this;
|
242 |
*
|
243 |
* @param int $step The number of indentation to add
|
244 |
*
|
245 |
+
* @return $this
|
246 |
*/
|
247 |
public function indent($step = 1)
|
248 |
{
|
256 |
*
|
257 |
* @param int $step The number of indentation to remove
|
258 |
*
|
259 |
+
* @return $this
|
260 |
*
|
261 |
* @throws LogicException When trying to outdent too much so the indentation would become negative
|
262 |
*/
|
264 |
{
|
265 |
// can't outdent by more steps than the current indentation level
|
266 |
if ($this->indentation < $step) {
|
267 |
+
throw new LogicException('Unable to call outdent() as the indentation would become negative.');
|
268 |
}
|
269 |
|
270 |
$this->indentation -= $step;
|
library/twig/twig/lib/Twig/CompilerInterface.php
CHANGED
@@ -21,9 +21,7 @@ interface Twig_CompilerInterface
|
|
21 |
/**
|
22 |
* Compiles a node.
|
23 |
*
|
24 |
-
* @
|
25 |
-
*
|
26 |
-
* @return Twig_CompilerInterface The current compiler instance
|
27 |
*/
|
28 |
public function compile(Twig_NodeInterface $node);
|
29 |
|
21 |
/**
|
22 |
* Compiles a node.
|
23 |
*
|
24 |
+
* @return $this
|
|
|
|
|
25 |
*/
|
26 |
public function compile(Twig_NodeInterface $node);
|
27 |
|
library/twig/twig/lib/Twig/Environment.php
CHANGED
@@ -16,7 +16,12 @@
|
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
-
const VERSION = '1.
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
protected $charset;
|
22 |
protected $loader;
|
@@ -49,6 +54,10 @@ class Twig_Environment
|
|
49 |
private $bcWriteCacheFile = false;
|
50 |
private $bcGetCacheFilename = false;
|
51 |
private $lastModifiedExtension = 0;
|
|
|
|
|
|
|
|
|
52 |
|
53 |
/**
|
54 |
* Constructor.
|
@@ -78,14 +87,14 @@ class Twig_Environment
|
|
78 |
* * false: disable auto-escaping
|
79 |
* * true: equivalent to html
|
80 |
* * html, js: set the autoescaping to one of the supported strategies
|
81 |
-
* *
|
82 |
-
* * PHP callback: a PHP callback that returns an escaping strategy based on the template "
|
83 |
*
|
84 |
* * optimizations: A flag that indicates which optimizations to apply
|
85 |
* (default to -1 which means that all optimizations are enabled;
|
86 |
* set it to 0 to disable).
|
87 |
*
|
88 |
-
* @param Twig_LoaderInterface $loader
|
89 |
* @param array $options An array of options
|
90 |
*/
|
91 |
public function __construct(Twig_LoaderInterface $loader = null, $options = array())
|
@@ -155,6 +164,7 @@ class Twig_Environment
|
|
155 |
public function setBaseTemplateClass($class)
|
156 |
{
|
157 |
$this->baseTemplateClass = $class;
|
|
|
158 |
}
|
159 |
|
160 |
/**
|
@@ -163,6 +173,7 @@ class Twig_Environment
|
|
163 |
public function enableDebug()
|
164 |
{
|
165 |
$this->debug = true;
|
|
|
166 |
}
|
167 |
|
168 |
/**
|
@@ -171,6 +182,7 @@ class Twig_Environment
|
|
171 |
public function disableDebug()
|
172 |
{
|
173 |
$this->debug = false;
|
|
|
174 |
}
|
175 |
|
176 |
/**
|
@@ -215,6 +227,7 @@ class Twig_Environment
|
|
215 |
public function enableStrictVariables()
|
216 |
{
|
217 |
$this->strictVariables = true;
|
|
|
218 |
}
|
219 |
|
220 |
/**
|
@@ -223,6 +236,7 @@ class Twig_Environment
|
|
223 |
public function disableStrictVariables()
|
224 |
{
|
225 |
$this->strictVariables = false;
|
|
|
226 |
}
|
227 |
|
228 |
/**
|
@@ -300,7 +314,10 @@ class Twig_Environment
|
|
300 |
*
|
301 |
* * The cache key for the given template;
|
302 |
* * The currently enabled extensions;
|
303 |
-
* * Whether the Twig C extension is available or not
|
|
|
|
|
|
|
304 |
*
|
305 |
* @param string $name The name for which to calculate the template class name
|
306 |
* @param int|null $index The index if it is an embedded template
|
@@ -309,10 +326,7 @@ class Twig_Environment
|
|
309 |
*/
|
310 |
public function getTemplateClass($name, $index = null)
|
311 |
{
|
312 |
-
$key = $this->getLoader()->getCacheKey($name);
|
313 |
-
$key .= json_encode(array_keys($this->extensions));
|
314 |
-
$key .= function_exists('twig_template_get_attributes');
|
315 |
-
$key .= ':'.PHP_MAJOR_VERSION.':'.PHP_MINOR_VERSION;
|
316 |
|
317 |
return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index);
|
318 |
}
|
@@ -364,7 +378,30 @@ class Twig_Environment
|
|
364 |
}
|
365 |
|
366 |
/**
|
367 |
-
* Loads a template
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
*
|
369 |
* @param string $name The template name
|
370 |
* @param int $index The index if it is an embedded template
|
@@ -373,6 +410,8 @@ class Twig_Environment
|
|
373 |
*
|
374 |
* @throws Twig_Error_Loader When the template cannot be found
|
375 |
* @throws Twig_Error_Syntax When an error occurred during compilation
|
|
|
|
|
376 |
*/
|
377 |
public function loadTemplate($name, $index = null)
|
378 |
{
|
@@ -394,14 +433,30 @@ class Twig_Environment
|
|
394 |
}
|
395 |
|
396 |
if (!class_exists($cls, false)) {
|
397 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
if ($this->bcWriteCacheFile) {
|
399 |
$this->writeCacheFile($key, $content);
|
400 |
} else {
|
401 |
$this->cache->write($key, $content);
|
|
|
402 |
}
|
403 |
|
404 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
}
|
406 |
}
|
407 |
|
@@ -546,7 +601,7 @@ class Twig_Environment
|
|
546 |
/**
|
547 |
* Gets the Lexer instance.
|
548 |
*
|
549 |
-
* @return Twig_LexerInterface
|
550 |
*
|
551 |
* @deprecated since 1.25 (to be removed in 2.0)
|
552 |
*/
|
@@ -561,11 +616,6 @@ class Twig_Environment
|
|
561 |
return $this->lexer;
|
562 |
}
|
563 |
|
564 |
-
/**
|
565 |
-
* Sets the Lexer instance.
|
566 |
-
*
|
567 |
-
* @param Twig_LexerInterface $lexer A Twig_LexerInterface instance
|
568 |
-
*/
|
569 |
public function setLexer(Twig_LexerInterface $lexer)
|
570 |
{
|
571 |
$this->lexer = $lexer;
|
@@ -574,26 +624,31 @@ class Twig_Environment
|
|
574 |
/**
|
575 |
* Tokenizes a source code.
|
576 |
*
|
577 |
-
* @param string $source The template source code
|
578 |
-
* @param string
|
579 |
*
|
580 |
-
* @return Twig_TokenStream
|
581 |
*
|
582 |
* @throws Twig_Error_Syntax When the code is syntactically wrong
|
583 |
*/
|
584 |
public function tokenize($source, $name = null)
|
585 |
{
|
|
|
|
|
|
|
|
|
|
|
586 |
if (null === $this->lexer) {
|
587 |
$this->lexer = new Twig_Lexer($this);
|
588 |
}
|
589 |
|
590 |
-
return $this->lexer->tokenize($source
|
591 |
}
|
592 |
|
593 |
/**
|
594 |
* Gets the Parser instance.
|
595 |
*
|
596 |
-
* @return Twig_ParserInterface
|
597 |
*
|
598 |
* @deprecated since 1.25 (to be removed in 2.0)
|
599 |
*/
|
@@ -608,11 +663,6 @@ class Twig_Environment
|
|
608 |
return $this->parser;
|
609 |
}
|
610 |
|
611 |
-
/**
|
612 |
-
* Sets the Parser instance.
|
613 |
-
*
|
614 |
-
* @param Twig_ParserInterface $parser A Twig_ParserInterface instance
|
615 |
-
*/
|
616 |
public function setParser(Twig_ParserInterface $parser)
|
617 |
{
|
618 |
$this->parser = $parser;
|
@@ -621,9 +671,7 @@ class Twig_Environment
|
|
621 |
/**
|
622 |
* Converts a token stream to a node tree.
|
623 |
*
|
624 |
-
* @
|
625 |
-
*
|
626 |
-
* @return Twig_Node_Module A node tree
|
627 |
*
|
628 |
* @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
|
629 |
*/
|
@@ -639,7 +687,7 @@ class Twig_Environment
|
|
639 |
/**
|
640 |
* Gets the Compiler instance.
|
641 |
*
|
642 |
-
* @return Twig_CompilerInterface
|
643 |
*
|
644 |
* @deprecated since 1.25 (to be removed in 2.0)
|
645 |
*/
|
@@ -654,11 +702,6 @@ class Twig_Environment
|
|
654 |
return $this->compiler;
|
655 |
}
|
656 |
|
657 |
-
/**
|
658 |
-
* Sets the Compiler instance.
|
659 |
-
*
|
660 |
-
* @param Twig_CompilerInterface $compiler A Twig_CompilerInterface instance
|
661 |
-
*/
|
662 |
public function setCompiler(Twig_CompilerInterface $compiler)
|
663 |
{
|
664 |
$this->compiler = $compiler;
|
@@ -667,8 +710,6 @@ class Twig_Environment
|
|
667 |
/**
|
668 |
* Compiles a node and returns the PHP code.
|
669 |
*
|
670 |
-
* @param Twig_NodeInterface $node A Twig_NodeInterface instance
|
671 |
-
*
|
672 |
* @return string The compiled PHP source code
|
673 |
*/
|
674 |
public function compile(Twig_NodeInterface $node)
|
@@ -683,8 +724,8 @@ class Twig_Environment
|
|
683 |
/**
|
684 |
* Compiles a template source code.
|
685 |
*
|
686 |
-
* @param string $source The template source code
|
687 |
-
* @param string
|
688 |
*
|
689 |
* @return string The compiled PHP source code
|
690 |
*
|
@@ -692,30 +733,34 @@ class Twig_Environment
|
|
692 |
*/
|
693 |
public function compileSource($source, $name = null)
|
694 |
{
|
|
|
|
|
|
|
|
|
|
|
695 |
try {
|
696 |
-
return $this->compile($this->parse($this->tokenize($source
|
697 |
} catch (Twig_Error $e) {
|
698 |
-
$e->
|
699 |
throw $e;
|
700 |
} catch (Exception $e) {
|
701 |
-
throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $
|
702 |
}
|
703 |
}
|
704 |
|
705 |
-
/**
|
706 |
-
* Sets the Loader instance.
|
707 |
-
*
|
708 |
-
* @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
|
709 |
-
*/
|
710 |
public function setLoader(Twig_LoaderInterface $loader)
|
711 |
{
|
|
|
|
|
|
|
|
|
712 |
$this->loader = $loader;
|
713 |
}
|
714 |
|
715 |
/**
|
716 |
* Gets the Loader instance.
|
717 |
*
|
718 |
-
* @return Twig_LoaderInterface
|
719 |
*/
|
720 |
public function getLoader()
|
721 |
{
|
@@ -771,51 +816,100 @@ class Twig_Environment
|
|
771 |
/**
|
772 |
* Returns true if the given extension is registered.
|
773 |
*
|
774 |
-
* @param string $
|
775 |
*
|
776 |
* @return bool Whether the extension is registered or not
|
777 |
*/
|
778 |
-
public function hasExtension($
|
779 |
{
|
780 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
781 |
}
|
782 |
|
783 |
/**
|
784 |
-
* Gets an extension by name.
|
785 |
*
|
786 |
-
* @param string $
|
787 |
*
|
788 |
-
* @return Twig_ExtensionInterface
|
789 |
*/
|
790 |
-
public function getExtension($
|
791 |
{
|
792 |
-
|
793 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
794 |
}
|
795 |
|
796 |
-
return $this->
|
797 |
}
|
798 |
|
799 |
/**
|
800 |
-
*
|
801 |
*
|
802 |
-
* @param
|
|
|
|
|
|
|
|
|
803 |
*/
|
804 |
-
public function
|
805 |
{
|
806 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
807 |
|
|
|
|
|
|
|
|
|
|
|
808 |
if ($this->extensionInitialized) {
|
809 |
-
throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $
|
810 |
}
|
811 |
|
812 |
-
|
813 |
-
|
|
|
|
|
|
|
|
|
814 |
}
|
815 |
|
816 |
$this->lastModifiedExtension = 0;
|
817 |
-
|
818 |
-
$this->extensions[$
|
|
|
819 |
}
|
820 |
|
821 |
/**
|
@@ -835,7 +929,17 @@ class Twig_Environment
|
|
835 |
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
|
836 |
}
|
837 |
|
838 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
839 |
}
|
840 |
|
841 |
/**
|
@@ -853,18 +957,13 @@ class Twig_Environment
|
|
853 |
/**
|
854 |
* Returns all registered extensions.
|
855 |
*
|
856 |
-
* @return
|
857 |
*/
|
858 |
public function getExtensions()
|
859 |
{
|
860 |
return $this->extensions;
|
861 |
}
|
862 |
|
863 |
-
/**
|
864 |
-
* Registers a Token Parser.
|
865 |
-
*
|
866 |
-
* @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
|
867 |
-
*/
|
868 |
public function addTokenParser(Twig_TokenParserInterface $parser)
|
869 |
{
|
870 |
if ($this->extensionInitialized) {
|
@@ -877,7 +976,7 @@ class Twig_Environment
|
|
877 |
/**
|
878 |
* Gets the registered Token Parsers.
|
879 |
*
|
880 |
-
* @return Twig_TokenParserBrokerInterface
|
881 |
*
|
882 |
* @internal
|
883 |
*/
|
@@ -895,7 +994,7 @@ class Twig_Environment
|
|
895 |
*
|
896 |
* Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
|
897 |
*
|
898 |
-
* @return Twig_TokenParserInterface[]
|
899 |
*
|
900 |
* @internal
|
901 |
*/
|
@@ -911,11 +1010,6 @@ class Twig_Environment
|
|
911 |
return $tags;
|
912 |
}
|
913 |
|
914 |
-
/**
|
915 |
-
* Registers a Node Visitor.
|
916 |
-
*
|
917 |
-
* @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
|
918 |
-
*/
|
919 |
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
|
920 |
{
|
921 |
if ($this->extensionInitialized) {
|
@@ -928,7 +1022,7 @@ class Twig_Environment
|
|
928 |
/**
|
929 |
* Gets the registered Node Visitors.
|
930 |
*
|
931 |
-
* @return Twig_NodeVisitorInterface[]
|
932 |
*
|
933 |
* @internal
|
934 |
*/
|
@@ -945,12 +1039,12 @@ class Twig_Environment
|
|
945 |
* Registers a Filter.
|
946 |
*
|
947 |
* @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance
|
948 |
-
* @param Twig_FilterInterface|Twig_SimpleFilter $filter
|
949 |
*/
|
950 |
public function addFilter($name, $filter = null)
|
951 |
{
|
952 |
if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
|
953 |
-
throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
|
954 |
}
|
955 |
|
956 |
if ($name instanceof Twig_SimpleFilter) {
|
@@ -1021,7 +1115,7 @@ class Twig_Environment
|
|
1021 |
*
|
1022 |
* Be warned that this method cannot return filters defined with registerUndefinedFilterCallback.
|
1023 |
*
|
1024 |
-
* @return Twig_FilterInterface[]
|
1025 |
*
|
1026 |
* @see registerUndefinedFilterCallback
|
1027 |
*
|
@@ -1045,7 +1139,7 @@ class Twig_Environment
|
|
1045 |
public function addTest($name, $test = null)
|
1046 |
{
|
1047 |
if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
|
1048 |
-
throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
|
1049 |
}
|
1050 |
|
1051 |
if ($name instanceof Twig_SimpleTest) {
|
@@ -1065,7 +1159,7 @@ class Twig_Environment
|
|
1065 |
/**
|
1066 |
* Gets the registered Tests.
|
1067 |
*
|
1068 |
-
* @return Twig_TestInterface[]
|
1069 |
*
|
1070 |
* @internal
|
1071 |
*/
|
@@ -1104,12 +1198,12 @@ class Twig_Environment
|
|
1104 |
* Registers a Function.
|
1105 |
*
|
1106 |
* @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance
|
1107 |
-
* @param Twig_FunctionInterface|Twig_SimpleFunction $function
|
1108 |
*/
|
1109 |
public function addFunction($name, $function = null)
|
1110 |
{
|
1111 |
if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
|
1112 |
-
throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
|
1113 |
}
|
1114 |
|
1115 |
if ($name instanceof Twig_SimpleFunction) {
|
@@ -1180,7 +1274,7 @@ class Twig_Environment
|
|
1180 |
*
|
1181 |
* Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
|
1182 |
*
|
1183 |
-
* @return Twig_FunctionInterface[]
|
1184 |
*
|
1185 |
* @see registerUndefinedFunctionCallback
|
1186 |
*
|
@@ -1407,7 +1501,7 @@ class Twig_Environment
|
|
1407 |
|
1408 |
$this->parsers->addTokenParserBroker($parser);
|
1409 |
} else {
|
1410 |
-
throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
|
1411 |
}
|
1412 |
}
|
1413 |
|
@@ -1434,4 +1528,21 @@ class Twig_Environment
|
|
1434 |
{
|
1435 |
$this->cache->write($file, $content);
|
1436 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1437 |
}
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
+
const VERSION = '1.28.2';
|
20 |
+
const VERSION_ID = 12802;
|
21 |
+
const MAJOR_VERSION = 1;
|
22 |
+
const MINOR_VERSION = 28;
|
23 |
+
const RELEASE_VERSION = 2;
|
24 |
+
const EXTRA_VERSION = '';
|
25 |
|
26 |
protected $charset;
|
27 |
protected $loader;
|
54 |
private $bcWriteCacheFile = false;
|
55 |
private $bcGetCacheFilename = false;
|
56 |
private $lastModifiedExtension = 0;
|
57 |
+
private $extensionsByClass = array();
|
58 |
+
private $runtimeLoaders = array();
|
59 |
+
private $runtimes = array();
|
60 |
+
private $optionsHash;
|
61 |
|
62 |
/**
|
63 |
* Constructor.
|
87 |
* * false: disable auto-escaping
|
88 |
* * true: equivalent to html
|
89 |
* * html, js: set the autoescaping to one of the supported strategies
|
90 |
+
* * name: set the autoescaping strategy based on the template name extension
|
91 |
+
* * PHP callback: a PHP callback that returns an escaping strategy based on the template "name"
|
92 |
*
|
93 |
* * optimizations: A flag that indicates which optimizations to apply
|
94 |
* (default to -1 which means that all optimizations are enabled;
|
95 |
* set it to 0 to disable).
|
96 |
*
|
97 |
+
* @param Twig_LoaderInterface $loader
|
98 |
* @param array $options An array of options
|
99 |
*/
|
100 |
public function __construct(Twig_LoaderInterface $loader = null, $options = array())
|
164 |
public function setBaseTemplateClass($class)
|
165 |
{
|
166 |
$this->baseTemplateClass = $class;
|
167 |
+
$this->updateOptionsHash();
|
168 |
}
|
169 |
|
170 |
/**
|
173 |
public function enableDebug()
|
174 |
{
|
175 |
$this->debug = true;
|
176 |
+
$this->updateOptionsHash();
|
177 |
}
|
178 |
|
179 |
/**
|
182 |
public function disableDebug()
|
183 |
{
|
184 |
$this->debug = false;
|
185 |
+
$this->updateOptionsHash();
|
186 |
}
|
187 |
|
188 |
/**
|
227 |
public function enableStrictVariables()
|
228 |
{
|
229 |
$this->strictVariables = true;
|
230 |
+
$this->updateOptionsHash();
|
231 |
}
|
232 |
|
233 |
/**
|
236 |
public function disableStrictVariables()
|
237 |
{
|
238 |
$this->strictVariables = false;
|
239 |
+
$this->updateOptionsHash();
|
240 |
}
|
241 |
|
242 |
/**
|
314 |
*
|
315 |
* * The cache key for the given template;
|
316 |
* * The currently enabled extensions;
|
317 |
+
* * Whether the Twig C extension is available or not;
|
318 |
+
* * PHP version;
|
319 |
+
* * Twig version;
|
320 |
+
* * Options with what environment was created.
|
321 |
*
|
322 |
* @param string $name The name for which to calculate the template class name
|
323 |
* @param int|null $index The index if it is an embedded template
|
326 |
*/
|
327 |
public function getTemplateClass($name, $index = null)
|
328 |
{
|
329 |
+
$key = $this->getLoader()->getCacheKey($name).$this->optionsHash;
|
|
|
|
|
|
|
330 |
|
331 |
return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index);
|
332 |
}
|
378 |
}
|
379 |
|
380 |
/**
|
381 |
+
* Loads a template.
|
382 |
+
*
|
383 |
+
* @param string|Twig_TemplateWrapper|Twig_Template $name The template name
|
384 |
+
*
|
385 |
+
* @return Twig_TemplateWrapper
|
386 |
+
*/
|
387 |
+
public function load($name)
|
388 |
+
{
|
389 |
+
if ($name instanceof Twig_TemplateWrapper) {
|
390 |
+
return $name;
|
391 |
+
}
|
392 |
+
|
393 |
+
if ($name instanceof Twig_Template) {
|
394 |
+
return new Twig_TemplateWrapper($this, $name);
|
395 |
+
}
|
396 |
+
|
397 |
+
return new Twig_TemplateWrapper($this, $this->loadTemplate($name));
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Loads a template internal representation.
|
402 |
+
*
|
403 |
+
* This method is for internal use only and should never be called
|
404 |
+
* directly.
|
405 |
*
|
406 |
* @param string $name The template name
|
407 |
* @param int $index The index if it is an embedded template
|
410 |
*
|
411 |
* @throws Twig_Error_Loader When the template cannot be found
|
412 |
* @throws Twig_Error_Syntax When an error occurred during compilation
|
413 |
+
*
|
414 |
+
* @internal
|
415 |
*/
|
416 |
public function loadTemplate($name, $index = null)
|
417 |
{
|
433 |
}
|
434 |
|
435 |
if (!class_exists($cls, false)) {
|
436 |
+
$loader = $this->getLoader();
|
437 |
+
if (!$loader instanceof Twig_SourceContextLoaderInterface) {
|
438 |
+
$source = new Twig_Source($loader->getSource($name), $name);
|
439 |
+
} else {
|
440 |
+
$source = $loader->getSourceContext($name);
|
441 |
+
}
|
442 |
+
|
443 |
+
$content = $this->compileSource($source);
|
444 |
+
|
445 |
if ($this->bcWriteCacheFile) {
|
446 |
$this->writeCacheFile($key, $content);
|
447 |
} else {
|
448 |
$this->cache->write($key, $content);
|
449 |
+
$this->cache->load($key);
|
450 |
}
|
451 |
|
452 |
+
if (!class_exists($cls, false)) {
|
453 |
+
/* Last line of defense if either $this->bcWriteCacheFile was used,
|
454 |
+
* $this->cache is implemented as a no-op or we have a race condition
|
455 |
+
* where the cache was cleared between the above calls to write to and load from
|
456 |
+
* the cache.
|
457 |
+
*/
|
458 |
+
eval('?>'.$content);
|
459 |
+
}
|
460 |
}
|
461 |
}
|
462 |
|
601 |
/**
|
602 |
* Gets the Lexer instance.
|
603 |
*
|
604 |
+
* @return Twig_LexerInterface
|
605 |
*
|
606 |
* @deprecated since 1.25 (to be removed in 2.0)
|
607 |
*/
|
616 |
return $this->lexer;
|
617 |
}
|
618 |
|
|
|
|
|
|
|
|
|
|
|
619 |
public function setLexer(Twig_LexerInterface $lexer)
|
620 |
{
|
621 |
$this->lexer = $lexer;
|
624 |
/**
|
625 |
* Tokenizes a source code.
|
626 |
*
|
627 |
+
* @param string|Twig_Source $source The template source code
|
628 |
+
* @param string $name The template name (deprecated)
|
629 |
*
|
630 |
+
* @return Twig_TokenStream
|
631 |
*
|
632 |
* @throws Twig_Error_Syntax When the code is syntactically wrong
|
633 |
*/
|
634 |
public function tokenize($source, $name = null)
|
635 |
{
|
636 |
+
if (!$source instanceof Twig_Source) {
|
637 |
+
@trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
|
638 |
+
$source = new Twig_Source($source, $name);
|
639 |
+
}
|
640 |
+
|
641 |
if (null === $this->lexer) {
|
642 |
$this->lexer = new Twig_Lexer($this);
|
643 |
}
|
644 |
|
645 |
+
return $this->lexer->tokenize($source);
|
646 |
}
|
647 |
|
648 |
/**
|
649 |
* Gets the Parser instance.
|
650 |
*
|
651 |
+
* @return Twig_ParserInterface
|
652 |
*
|
653 |
* @deprecated since 1.25 (to be removed in 2.0)
|
654 |
*/
|
663 |
return $this->parser;
|
664 |
}
|
665 |
|
|
|
|
|
|
|
|
|
|
|
666 |
public function setParser(Twig_ParserInterface $parser)
|
667 |
{
|
668 |
$this->parser = $parser;
|
671 |
/**
|
672 |
* Converts a token stream to a node tree.
|
673 |
*
|
674 |
+
* @return Twig_Node_Module
|
|
|
|
|
675 |
*
|
676 |
* @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
|
677 |
*/
|
687 |
/**
|
688 |
* Gets the Compiler instance.
|
689 |
*
|
690 |
+
* @return Twig_CompilerInterface
|
691 |
*
|
692 |
* @deprecated since 1.25 (to be removed in 2.0)
|
693 |
*/
|
702 |
return $this->compiler;
|
703 |
}
|
704 |
|
|
|
|
|
|
|
|
|
|
|
705 |
public function setCompiler(Twig_CompilerInterface $compiler)
|
706 |
{
|
707 |
$this->compiler = $compiler;
|
710 |
/**
|
711 |
* Compiles a node and returns the PHP code.
|
712 |
*
|
|
|
|
|
713 |
* @return string The compiled PHP source code
|
714 |
*/
|
715 |
public function compile(Twig_NodeInterface $node)
|
724 |
/**
|
725 |
* Compiles a template source code.
|
726 |
*
|
727 |
+
* @param string|Twig_Source $source The template source code
|
728 |
+
* @param string $name The template name (deprecated)
|
729 |
*
|
730 |
* @return string The compiled PHP source code
|
731 |
*
|
733 |
*/
|
734 |
public function compileSource($source, $name = null)
|
735 |
{
|
736 |
+
if (!$source instanceof Twig_Source) {
|
737 |
+
@trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
|
738 |
+
$source = new Twig_Source($source, $name);
|
739 |
+
}
|
740 |
+
|
741 |
try {
|
742 |
+
return $this->compile($this->parse($this->tokenize($source)));
|
743 |
} catch (Twig_Error $e) {
|
744 |
+
$e->setTemplateName($source->getName());
|
745 |
throw $e;
|
746 |
} catch (Exception $e) {
|
747 |
+
throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source->getName(), $e);
|
748 |
}
|
749 |
}
|
750 |
|
|
|
|
|
|
|
|
|
|
|
751 |
public function setLoader(Twig_LoaderInterface $loader)
|
752 |
{
|
753 |
+
if (!$loader instanceof Twig_SourceContextLoaderInterface && 0 !== strpos(get_class($loader), 'Mock_Twig_LoaderInterface')) {
|
754 |
+
@trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.', get_class($loader)), E_USER_DEPRECATED);
|
755 |
+
}
|
756 |
+
|
757 |
$this->loader = $loader;
|
758 |
}
|
759 |
|
760 |
/**
|
761 |
* Gets the Loader instance.
|
762 |
*
|
763 |
+
* @return Twig_LoaderInterface
|
764 |
*/
|
765 |
public function getLoader()
|
766 |
{
|
816 |
/**
|
817 |
* Returns true if the given extension is registered.
|
818 |
*
|
819 |
+
* @param string $class The extension class name
|
820 |
*
|
821 |
* @return bool Whether the extension is registered or not
|
822 |
*/
|
823 |
+
public function hasExtension($class)
|
824 |
{
|
825 |
+
$class = ltrim($class, '\\');
|
826 |
+
if (isset($this->extensions[$class])) {
|
827 |
+
if ($class !== get_class($this->extensions[$class])) {
|
828 |
+
@trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
|
829 |
+
}
|
830 |
+
|
831 |
+
return true;
|
832 |
+
}
|
833 |
+
|
834 |
+
return isset($this->extensionsByClass[ltrim($class, '\\')]);
|
835 |
+
}
|
836 |
+
|
837 |
+
/**
|
838 |
+
* Adds a runtime loader.
|
839 |
+
*/
|
840 |
+
public function addRuntimeLoader(Twig_RuntimeLoaderInterface $loader)
|
841 |
+
{
|
842 |
+
$this->runtimeLoaders[] = $loader;
|
843 |
}
|
844 |
|
845 |
/**
|
846 |
+
* Gets an extension by class name.
|
847 |
*
|
848 |
+
* @param string $class The extension class name
|
849 |
*
|
850 |
+
* @return Twig_ExtensionInterface
|
851 |
*/
|
852 |
+
public function getExtension($class)
|
853 |
{
|
854 |
+
$class = ltrim($class, '\\');
|
855 |
+
|
856 |
+
if (isset($this->extensions[$class])) {
|
857 |
+
if ($class !== get_class($this->extensions[$class])) {
|
858 |
+
@trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
|
859 |
+
}
|
860 |
+
|
861 |
+
return $this->extensions[$class];
|
862 |
+
}
|
863 |
+
|
864 |
+
if (!isset($this->extensionsByClass[$class])) {
|
865 |
+
throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $class));
|
866 |
}
|
867 |
|
868 |
+
return $this->extensionsByClass[$class];
|
869 |
}
|
870 |
|
871 |
/**
|
872 |
+
* Returns the runtime implementation of a Twig element (filter/function/test).
|
873 |
*
|
874 |
+
* @param string $class A runtime class name
|
875 |
+
*
|
876 |
+
* @return object The runtime implementation
|
877 |
+
*
|
878 |
+
* @throws Twig_Error_Runtime When the template cannot be found
|
879 |
*/
|
880 |
+
public function getRuntime($class)
|
881 |
{
|
882 |
+
if (isset($this->runtimes[$class])) {
|
883 |
+
return $this->runtimes[$class];
|
884 |
+
}
|
885 |
+
|
886 |
+
foreach ($this->runtimeLoaders as $loader) {
|
887 |
+
if (null !== $runtime = $loader->load($class)) {
|
888 |
+
return $this->runtimes[$class] = $runtime;
|
889 |
+
}
|
890 |
+
}
|
891 |
|
892 |
+
throw new Twig_Error_Runtime(sprintf('Unable to load the "%s" runtime.', $class));
|
893 |
+
}
|
894 |
+
|
895 |
+
public function addExtension(Twig_ExtensionInterface $extension)
|
896 |
+
{
|
897 |
if ($this->extensionInitialized) {
|
898 |
+
throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
|
899 |
}
|
900 |
|
901 |
+
$class = get_class($extension);
|
902 |
+
if ($class !== $extension->getName()) {
|
903 |
+
if (isset($this->extensions[$extension->getName()])) {
|
904 |
+
unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]);
|
905 |
+
@trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $extension->getName()), E_USER_DEPRECATED);
|
906 |
+
}
|
907 |
}
|
908 |
|
909 |
$this->lastModifiedExtension = 0;
|
910 |
+
$this->extensionsByClass[$class] = $extension;
|
911 |
+
$this->extensions[$extension->getName()] = $extension;
|
912 |
+
$this->updateOptionsHash();
|
913 |
}
|
914 |
|
915 |
/**
|
929 |
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
|
930 |
}
|
931 |
|
932 |
+
$class = ltrim($name, '\\');
|
933 |
+
if (isset($this->extensions[$class])) {
|
934 |
+
if ($class !== get_class($this->extensions[$class])) {
|
935 |
+
@trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
|
936 |
+
}
|
937 |
+
|
938 |
+
unset($this->extensions[$class]);
|
939 |
+
}
|
940 |
+
|
941 |
+
unset($this->extensions[$class]);
|
942 |
+
$this->updateOptionsHash();
|
943 |
}
|
944 |
|
945 |
/**
|
957 |
/**
|
958 |
* Returns all registered extensions.
|
959 |
*
|
960 |
+
* @return Twig_ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on)
|
961 |
*/
|
962 |
public function getExtensions()
|
963 |
{
|
964 |
return $this->extensions;
|
965 |
}
|
966 |
|
|
|
|
|
|
|
|
|
|
|
967 |
public function addTokenParser(Twig_TokenParserInterface $parser)
|
968 |
{
|
969 |
if ($this->extensionInitialized) {
|
976 |
/**
|
977 |
* Gets the registered Token Parsers.
|
978 |
*
|
979 |
+
* @return Twig_TokenParserBrokerInterface
|
980 |
*
|
981 |
* @internal
|
982 |
*/
|
994 |
*
|
995 |
* Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
|
996 |
*
|
997 |
+
* @return Twig_TokenParserInterface[]
|
998 |
*
|
999 |
* @internal
|
1000 |
*/
|
1010 |
return $tags;
|
1011 |
}
|
1012 |
|
|
|
|
|
|
|
|
|
|
|
1013 |
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
|
1014 |
{
|
1015 |
if ($this->extensionInitialized) {
|
1022 |
/**
|
1023 |
* Gets the registered Node Visitors.
|
1024 |
*
|
1025 |
+
* @return Twig_NodeVisitorInterface[]
|
1026 |
*
|
1027 |
* @internal
|
1028 |
*/
|
1039 |
* Registers a Filter.
|
1040 |
*
|
1041 |
* @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance
|
1042 |
+
* @param Twig_FilterInterface|Twig_SimpleFilter $filter
|
1043 |
*/
|
1044 |
public function addFilter($name, $filter = null)
|
1045 |
{
|
1046 |
if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
|
1047 |
+
throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter.');
|
1048 |
}
|
1049 |
|
1050 |
if ($name instanceof Twig_SimpleFilter) {
|
1115 |
*
|
1116 |
* Be warned that this method cannot return filters defined with registerUndefinedFilterCallback.
|
1117 |
*
|
1118 |
+
* @return Twig_FilterInterface[]
|
1119 |
*
|
1120 |
* @see registerUndefinedFilterCallback
|
1121 |
*
|
1139 |
public function addTest($name, $test = null)
|
1140 |
{
|
1141 |
if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
|
1142 |
+
throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest.');
|
1143 |
}
|
1144 |
|
1145 |
if ($name instanceof Twig_SimpleTest) {
|
1159 |
/**
|
1160 |
* Gets the registered Tests.
|
1161 |
*
|
1162 |
+
* @return Twig_TestInterface[]
|
1163 |
*
|
1164 |
* @internal
|
1165 |
*/
|
1198 |
* Registers a Function.
|
1199 |
*
|
1200 |
* @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance
|
1201 |
+
* @param Twig_FunctionInterface|Twig_SimpleFunction $function
|
1202 |
*/
|
1203 |
public function addFunction($name, $function = null)
|
1204 |
{
|
1205 |
if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
|
1206 |
+
throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction.');
|
1207 |
}
|
1208 |
|
1209 |
if ($name instanceof Twig_SimpleFunction) {
|
1274 |
*
|
1275 |
* Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
|
1276 |
*
|
1277 |
+
* @return Twig_FunctionInterface[]
|
1278 |
*
|
1279 |
* @see registerUndefinedFunctionCallback
|
1280 |
*
|
1501 |
|
1502 |
$this->parsers->addTokenParserBroker($parser);
|
1503 |
} else {
|
1504 |
+
throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances.');
|
1505 |
}
|
1506 |
}
|
1507 |
|
1528 |
{
|
1529 |
$this->cache->write($file, $content);
|
1530 |
}
|
1531 |
+
|
1532 |
+
private function updateOptionsHash()
|
1533 |
+
{
|
1534 |
+
$hashParts = array_merge(
|
1535 |
+
array_keys($this->extensions),
|
1536 |
+
array(
|
1537 |
+
(int) function_exists('twig_template_get_attributes'),
|
1538 |
+
PHP_MAJOR_VERSION,
|
1539 |
+
PHP_MINOR_VERSION,
|
1540 |
+
self::VERSION,
|
1541 |
+
(int) $this->debug,
|
1542 |
+
$this->baseTemplateClass,
|
1543 |
+
(int) $this->strictVariables,
|
1544 |
+
)
|
1545 |
+
);
|
1546 |
+
$this->optionsHash = implode(':', $hashParts);
|
1547 |
+
}
|
1548 |
}
|
library/twig/twig/lib/Twig/Error.php
CHANGED
@@ -25,8 +25,8 @@
|
|
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
|
29 |
-
* can be disabled by passing false for both the
|
30 |
* when creating a new instance of this class.
|
31 |
*
|
32 |
* @author Fabien Potencier <fabien@symfony.com>
|
@@ -34,6 +34,7 @@
|
|
34 |
class Twig_Error extends Exception
|
35 |
{
|
36 |
protected $lineno;
|
|
|
37 |
protected $filename;
|
38 |
protected $rawMessage;
|
39 |
protected $previous;
|
@@ -41,21 +42,21 @@ class Twig_Error extends Exception
|
|
41 |
/**
|
42 |
* Constructor.
|
43 |
*
|
44 |
-
* Set both the line number and the
|
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
|
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 $
|
56 |
* @param Exception $previous The previous exception
|
57 |
*/
|
58 |
-
public function __construct($message, $lineno = -1, $
|
59 |
{
|
60 |
if (PHP_VERSION_ID < 50300) {
|
61 |
$this->previous = $previous;
|
@@ -65,9 +66,9 @@ class Twig_Error extends Exception
|
|
65 |
}
|
66 |
|
67 |
$this->lineno = $lineno;
|
68 |
-
$this->filename = $
|
69 |
|
70 |
-
if (-1 === $
|
71 |
$this->guessTemplateInfo();
|
72 |
}
|
73 |
|
@@ -87,23 +88,53 @@ class Twig_Error extends Exception
|
|
87 |
}
|
88 |
|
89 |
/**
|
90 |
-
* Gets the
|
91 |
*
|
92 |
-
* @return string The
|
|
|
|
|
93 |
*/
|
94 |
public function getTemplateFile()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
{
|
96 |
return $this->filename;
|
97 |
}
|
98 |
|
99 |
/**
|
100 |
-
* Sets the
|
101 |
*
|
102 |
-
* @param string $
|
103 |
*/
|
104 |
-
public function
|
105 |
{
|
106 |
-
$this->filename = $
|
107 |
|
108 |
$this->updateRepr();
|
109 |
}
|
@@ -182,11 +213,11 @@ class Twig_Error extends Exception
|
|
182 |
|
183 |
if ($this->filename) {
|
184 |
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
|
185 |
-
$
|
186 |
} else {
|
187 |
-
$
|
188 |
}
|
189 |
-
$this->message .= sprintf(' in %s', $
|
190 |
}
|
191 |
|
192 |
if ($this->lineno && $this->lineno >= 0) {
|
@@ -227,7 +258,7 @@ class Twig_Error extends Exception
|
|
227 |
}
|
228 |
}
|
229 |
|
230 |
-
// update template
|
231 |
if (null !== $template && null === $this->filename) {
|
232 |
$this->filename = $template->getTemplateName();
|
233 |
}
|
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 name is set to null). As this is a costly operation, this
|
29 |
+
* can be disabled by passing false for both the name and the line number
|
30 |
* when creating a new instance of this class.
|
31 |
*
|
32 |
* @author Fabien Potencier <fabien@symfony.com>
|
34 |
class Twig_Error extends Exception
|
35 |
{
|
36 |
protected $lineno;
|
37 |
+
// to be renamed to name in 2.0
|
38 |
protected $filename;
|
39 |
protected $rawMessage;
|
40 |
protected $previous;
|
42 |
/**
|
43 |
* Constructor.
|
44 |
*
|
45 |
+
* Set both the line number and the name to false to
|
46 |
* disable automatic guessing of the original template name
|
47 |
* and line number.
|
48 |
*
|
49 |
* Set the line number to -1 to enable its automatic guessing.
|
50 |
+
* Set the name to null to enable its automatic guessing.
|
51 |
*
|
52 |
* By default, automatic guessing is enabled.
|
53 |
*
|
54 |
* @param string $message The error message
|
55 |
* @param int $lineno The template line where the error occurred
|
56 |
+
* @param string $name The template logical name where the error occurred
|
57 |
* @param Exception $previous The previous exception
|
58 |
*/
|
59 |
+
public function __construct($message, $lineno = -1, $name = null, Exception $previous = null)
|
60 |
{
|
61 |
if (PHP_VERSION_ID < 50300) {
|
62 |
$this->previous = $previous;
|
66 |
}
|
67 |
|
68 |
$this->lineno = $lineno;
|
69 |
+
$this->filename = $name;
|
70 |
|
71 |
+
if (-1 === $lineno || null === $name) {
|
72 |
$this->guessTemplateInfo();
|
73 |
}
|
74 |
|
88 |
}
|
89 |
|
90 |
/**
|
91 |
+
* Gets the logical name where the error occurred.
|
92 |
*
|
93 |
+
* @return string The name
|
94 |
+
*
|
95 |
+
* @deprecated since 1.27 (to be removed in 2.0). Use getTemplateName() instead.
|
96 |
*/
|
97 |
public function getTemplateFile()
|
98 |
+
{
|
99 |
+
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', __METHOD__), E_USER_DEPRECATED);
|
100 |
+
|
101 |
+
return $this->filename;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Sets the logical name where the error occurred.
|
106 |
+
*
|
107 |
+
* @param string $name The name
|
108 |
+
*
|
109 |
+
* @deprecated since 1.27 (to be removed in 2.0). Use setTemplateName() instead.
|
110 |
+
*/
|
111 |
+
public function setTemplateFile($name)
|
112 |
+
{
|
113 |
+
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', __METHOD__), E_USER_DEPRECATED);
|
114 |
+
|
115 |
+
$this->filename = $name;
|
116 |
+
|
117 |
+
$this->updateRepr();
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Gets the logical name where the error occurred.
|
122 |
+
*
|
123 |
+
* @return string The name
|
124 |
+
*/
|
125 |
+
public function getTemplateName()
|
126 |
{
|
127 |
return $this->filename;
|
128 |
}
|
129 |
|
130 |
/**
|
131 |
+
* Sets the logical name where the error occurred.
|
132 |
*
|
133 |
+
* @param string $name The name
|
134 |
*/
|
135 |
+
public function setTemplateName($name)
|
136 |
{
|
137 |
+
$this->filename = $name;
|
138 |
|
139 |
$this->updateRepr();
|
140 |
}
|
213 |
|
214 |
if ($this->filename) {
|
215 |
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
|
216 |
+
$name = sprintf('"%s"', $this->filename);
|
217 |
} else {
|
218 |
+
$name = json_encode($this->filename);
|
219 |
}
|
220 |
+
$this->message .= sprintf(' in %s', $name);
|
221 |
}
|
222 |
|
223 |
if ($this->lineno && $this->lineno >= 0) {
|
258 |
}
|
259 |
}
|
260 |
|
261 |
+
// update template name
|
262 |
if (null !== $template && null === $this->filename) {
|
263 |
$this->filename = $template->getTemplateName();
|
264 |
}
|
library/twig/twig/lib/Twig/ExpressionParser.php
CHANGED
@@ -19,6 +19,8 @@
|
|
19 |
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
|
|
|
|
22 |
*/
|
23 |
class Twig_ExpressionParser
|
24 |
{
|
@@ -29,11 +31,23 @@ class Twig_ExpressionParser
|
|
29 |
protected $unaryOperators;
|
30 |
protected $binaryOperators;
|
31 |
|
32 |
-
|
|
|
|
|
33 |
{
|
34 |
$this->parser = $parser;
|
35 |
-
|
36 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
}
|
38 |
|
39 |
public function parseExpression($precedence = 0)
|
@@ -44,7 +58,11 @@ class Twig_ExpressionParser
|
|
44 |
$op = $this->binaryOperators[$token->getValue()];
|
45 |
$this->parser->getStream()->next();
|
46 |
|
47 |
-
if (
|
|
|
|
|
|
|
|
|
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']);
|
@@ -171,7 +189,7 @@ class Twig_ExpressionParser
|
|
171 |
$negClass = 'Twig_Node_Expression_Unary_Neg';
|
172 |
$posClass = 'Twig_Node_Expression_Unary_Pos';
|
173 |
if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) {
|
174 |
-
throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->
|
175 |
}
|
176 |
|
177 |
$this->parser->getStream()->next();
|
@@ -187,7 +205,7 @@ class Twig_ExpressionParser
|
|
187 |
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
|
188 |
$node = $this->parseHashExpression();
|
189 |
} else {
|
190 |
-
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->
|
191 |
}
|
192 |
}
|
193 |
|
@@ -216,7 +234,7 @@ class Twig_ExpressionParser
|
|
216 |
|
217 |
$expr = array_shift($nodes);
|
218 |
foreach ($nodes as $node) {
|
219 |
-
$expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->
|
220 |
}
|
221 |
|
222 |
return $expr;
|
@@ -278,7 +296,7 @@ class Twig_ExpressionParser
|
|
278 |
} else {
|
279 |
$current = $stream->getCurrent();
|
280 |
|
281 |
-
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(), $
|
282 |
}
|
283 |
|
284 |
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
|
@@ -317,20 +335,25 @@ class Twig_ExpressionParser
|
|
317 |
case 'parent':
|
318 |
$this->parseArguments();
|
319 |
if (!count($this->parser->getBlockStack())) {
|
320 |
-
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->
|
321 |
}
|
322 |
|
323 |
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
324 |
-
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->
|
325 |
}
|
326 |
|
327 |
return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
|
328 |
case 'block':
|
329 |
-
|
|
|
|
|
|
|
|
|
|
|
330 |
case 'attribute':
|
331 |
$args = $this->parseArguments();
|
332 |
if (count($args) < 2) {
|
333 |
-
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->
|
334 |
}
|
335 |
|
336 |
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line);
|
@@ -379,18 +402,18 @@ class Twig_ExpressionParser
|
|
379 |
}
|
380 |
}
|
381 |
} else {
|
382 |
-
throw new Twig_Error_Syntax('Expected name or number', $lineno, $
|
383 |
}
|
384 |
|
385 |
if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
386 |
if (!$arg instanceof Twig_Node_Expression_Constant) {
|
387 |
-
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $
|
388 |
}
|
389 |
|
390 |
$name = $arg->getAttribute('value');
|
391 |
|
392 |
if ($this->parser->isReservedMacroName($name)) {
|
393 |
-
throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $
|
394 |
}
|
395 |
|
396 |
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno);
|
@@ -500,7 +523,7 @@ class Twig_ExpressionParser
|
|
500 |
$name = null;
|
501 |
if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
|
502 |
if (!$value instanceof Twig_Node_Expression_Name) {
|
503 |
-
throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $
|
504 |
}
|
505 |
$name = $value->getAttribute('name');
|
506 |
|
@@ -508,7 +531,7 @@ class Twig_ExpressionParser
|
|
508 |
$value = $this->parsePrimaryExpression();
|
509 |
|
510 |
if (!$this->checkConstantExpression($value)) {
|
511 |
-
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(), $
|
512 |
}
|
513 |
} else {
|
514 |
$value = $this->parseExpression();
|
@@ -536,16 +559,17 @@ class Twig_ExpressionParser
|
|
536 |
|
537 |
public function parseAssignmentExpression()
|
538 |
{
|
|
|
539 |
$targets = array();
|
540 |
while (true) {
|
541 |
-
$token = $
|
542 |
$value = $token->getValue();
|
543 |
if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) {
|
544 |
-
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $value), $token->getLine(), $
|
545 |
}
|
546 |
$targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine());
|
547 |
|
548 |
-
if (!$
|
549 |
break;
|
550 |
}
|
551 |
}
|
@@ -566,13 +590,79 @@ class Twig_ExpressionParser
|
|
566 |
return new Twig_Node($targets);
|
567 |
}
|
568 |
|
569 |
-
|
570 |
{
|
571 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
572 |
|
573 |
-
|
574 |
-
|
575 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
576 |
|
577 |
throw $e;
|
578 |
}
|
@@ -585,7 +675,7 @@ class Twig_ExpressionParser
|
|
585 |
if ($function->getAlternative()) {
|
586 |
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
|
587 |
}
|
588 |
-
$message .= sprintf(' in %s at line %d.', $this->parser->
|
589 |
|
590 |
@trigger_error($message, E_USER_DEPRECATED);
|
591 |
}
|
@@ -599,11 +689,9 @@ class Twig_ExpressionParser
|
|
599 |
|
600 |
protected function getFilterNodeClass($name, $line)
|
601 |
{
|
602 |
-
$
|
603 |
-
|
604 |
-
|
605 |
-
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getFilename());
|
606 |
-
$e->addSuggestions($name, array_keys($env->getFilters()));
|
607 |
|
608 |
throw $e;
|
609 |
}
|
@@ -616,7 +704,7 @@ class Twig_ExpressionParser
|
|
616 |
if ($filter->getAlternative()) {
|
617 |
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
|
618 |
}
|
619 |
-
$message .= sprintf(' in %s at line %d.', $this->parser->
|
620 |
|
621 |
@trigger_error($message, E_USER_DEPRECATED);
|
622 |
}
|
19 |
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
+
*
|
23 |
+
* @internal
|
24 |
*/
|
25 |
class Twig_ExpressionParser
|
26 |
{
|
31 |
protected $unaryOperators;
|
32 |
protected $binaryOperators;
|
33 |
|
34 |
+
private $env;
|
35 |
+
|
36 |
+
public function __construct(Twig_Parser $parser, Twig_Environment $env = null)
|
37 |
{
|
38 |
$this->parser = $parser;
|
39 |
+
|
40 |
+
if ($env instanceof Twig_Environment) {
|
41 |
+
$this->env = $env;
|
42 |
+
$this->unaryOperators = $env->getUnaryOperators();
|
43 |
+
$this->binaryOperators = $env->getBinaryOperators();
|
44 |
+
} else {
|
45 |
+
@trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED);
|
46 |
+
|
47 |
+
$this->env = $parser->getEnvironment();
|
48 |
+
$this->unaryOperators = func_get_arg(1);
|
49 |
+
$this->binaryOperators = func_get_arg(2);
|
50 |
+
}
|
51 |
}
|
52 |
|
53 |
public function parseExpression($precedence = 0)
|
58 |
$op = $this->binaryOperators[$token->getValue()];
|
59 |
$this->parser->getStream()->next();
|
60 |
|
61 |
+
if ('is not' === $token->getValue()) {
|
62 |
+
$expr = $this->parseNotTestExpression($expr);
|
63 |
+
} elseif ('is' === $token->getValue()) {
|
64 |
+
$expr = $this->parseTestExpression($expr);
|
65 |
+
} elseif (isset($op['callable'])) {
|
66 |
$expr = call_user_func($op['callable'], $this->parser, $expr);
|
67 |
} else {
|
68 |
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
|
189 |
$negClass = 'Twig_Node_Expression_Unary_Neg';
|
190 |
$posClass = 'Twig_Node_Expression_Unary_Pos';
|
191 |
if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) {
|
192 |
+
throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()->getName());
|
193 |
}
|
194 |
|
195 |
$this->parser->getStream()->next();
|
205 |
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
|
206 |
$node = $this->parseHashExpression();
|
207 |
} else {
|
208 |
+
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()->getName());
|
209 |
}
|
210 |
}
|
211 |
|
234 |
|
235 |
$expr = array_shift($nodes);
|
236 |
foreach ($nodes as $node) {
|
237 |
+
$expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getTemplateLine());
|
238 |
}
|
239 |
|
240 |
return $expr;
|
296 |
} else {
|
297 |
$current = $stream->getCurrent();
|
298 |
|
299 |
+
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(), $stream->getSourceContext()->getName());
|
300 |
}
|
301 |
|
302 |
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
|
335 |
case 'parent':
|
336 |
$this->parseArguments();
|
337 |
if (!count($this->parser->getBlockStack())) {
|
338 |
+
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext()->getName());
|
339 |
}
|
340 |
|
341 |
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
342 |
+
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext()->getName());
|
343 |
}
|
344 |
|
345 |
return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
|
346 |
case 'block':
|
347 |
+
$args = $this->parseArguments();
|
348 |
+
if (count($args) < 1) {
|
349 |
+
throw new Twig_Error_Syntax('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()->getName());
|
350 |
+
}
|
351 |
+
|
352 |
+
return new Twig_Node_Expression_BlockReference($args->getNode(0), count($args) > 1 ? $args->getNode(1) : null, $line);
|
353 |
case 'attribute':
|
354 |
$args = $this->parseArguments();
|
355 |
if (count($args) < 2) {
|
356 |
+
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext()->getName());
|
357 |
}
|
358 |
|
359 |
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line);
|
402 |
}
|
403 |
}
|
404 |
} else {
|
405 |
+
throw new Twig_Error_Syntax('Expected name or number.', $lineno, $stream->getSourceContext()->getName());
|
406 |
}
|
407 |
|
408 |
if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
409 |
if (!$arg instanceof Twig_Node_Expression_Constant) {
|
410 |
+
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()->getName());
|
411 |
}
|
412 |
|
413 |
$name = $arg->getAttribute('value');
|
414 |
|
415 |
if ($this->parser->isReservedMacroName($name)) {
|
416 |
+
throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()->getName());
|
417 |
}
|
418 |
|
419 |
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno);
|
523 |
$name = null;
|
524 |
if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
|
525 |
if (!$value instanceof Twig_Node_Expression_Name) {
|
526 |
+
throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $stream->getSourceContext()->getName());
|
527 |
}
|
528 |
$name = $value->getAttribute('name');
|
529 |
|
531 |
$value = $this->parsePrimaryExpression();
|
532 |
|
533 |
if (!$this->checkConstantExpression($value)) {
|
534 |
+
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(), $stream->getSourceContext()->getName());
|
535 |
}
|
536 |
} else {
|
537 |
$value = $this->parseExpression();
|
559 |
|
560 |
public function parseAssignmentExpression()
|
561 |
{
|
562 |
+
$stream = $this->parser->getStream();
|
563 |
$targets = array();
|
564 |
while (true) {
|
565 |
+
$token = $stream->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
|
566 |
$value = $token->getValue();
|
567 |
if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) {
|
568 |
+
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()->getName());
|
569 |
}
|
570 |
$targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine());
|
571 |
|
572 |
+
if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
|
573 |
break;
|
574 |
}
|
575 |
}
|
590 |
return new Twig_Node($targets);
|
591 |
}
|
592 |
|
593 |
+
private function parseNotTestExpression(Twig_NodeInterface $node)
|
594 |
{
|
595 |
+
return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine());
|
596 |
+
}
|
597 |
+
|
598 |
+
private function parseTestExpression(Twig_NodeInterface $node)
|
599 |
+
{
|
600 |
+
$stream = $this->parser->getStream();
|
601 |
+
list($name, $test) = $this->getTest($node->getTemplateLine());
|
602 |
+
|
603 |
+
$class = $this->getTestNodeClass($test);
|
604 |
+
$arguments = null;
|
605 |
+
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
606 |
+
$arguments = $this->parser->getExpressionParser()->parseArguments(true);
|
607 |
+
}
|
608 |
|
609 |
+
return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine());
|
610 |
+
}
|
611 |
+
|
612 |
+
private function getTest($line)
|
613 |
+
{
|
614 |
+
$stream = $this->parser->getStream();
|
615 |
+
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
616 |
+
|
617 |
+
if ($test = $this->env->getTest($name)) {
|
618 |
+
return array($name, $test);
|
619 |
+
}
|
620 |
+
|
621 |
+
if ($stream->test(Twig_Token::NAME_TYPE)) {
|
622 |
+
// try 2-words tests
|
623 |
+
$name = $name.' '.$this->parser->getCurrentToken()->getValue();
|
624 |
+
|
625 |
+
if ($test = $this->env->getTest($name)) {
|
626 |
+
$stream->next();
|
627 |
+
|
628 |
+
return array($name, $test);
|
629 |
+
}
|
630 |
+
}
|
631 |
+
|
632 |
+
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()->getName());
|
633 |
+
$e->addSuggestions($name, array_keys($this->env->getTests()));
|
634 |
+
|
635 |
+
throw $e;
|
636 |
+
}
|
637 |
+
|
638 |
+
private function getTestNodeClass($test)
|
639 |
+
{
|
640 |
+
if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
|
641 |
+
$stream = $this->parser->getStream();
|
642 |
+
$message = sprintf('Twig Test "%s" is deprecated', $test->getName());
|
643 |
+
if (!is_bool($test->getDeprecatedVersion())) {
|
644 |
+
$message .= sprintf(' since version %s', $test->getDeprecatedVersion());
|
645 |
+
}
|
646 |
+
if ($test->getAlternative()) {
|
647 |
+
$message .= sprintf('. Use "%s" instead', $test->getAlternative());
|
648 |
+
}
|
649 |
+
$message .= sprintf(' in %s at line %d.', $stream->getSourceContext()->getName(), $stream->getCurrent()->getLine());
|
650 |
+
|
651 |
+
@trigger_error($message, E_USER_DEPRECATED);
|
652 |
+
}
|
653 |
+
|
654 |
+
if ($test instanceof Twig_SimpleTest) {
|
655 |
+
return $test->getNodeClass();
|
656 |
+
}
|
657 |
+
|
658 |
+
return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test';
|
659 |
+
}
|
660 |
+
|
661 |
+
protected function getFunctionNodeClass($name, $line)
|
662 |
+
{
|
663 |
+
if (false === $function = $this->env->getFunction($name)) {
|
664 |
+
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()->getName());
|
665 |
+
$e->addSuggestions($name, array_keys($this->env->getFunctions()));
|
666 |
|
667 |
throw $e;
|
668 |
}
|
675 |
if ($function->getAlternative()) {
|
676 |
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
|
677 |
}
|
678 |
+
$message .= sprintf(' in %s at line %d.', $this->parser->getStream()->getSourceContext()->getName(), $line);
|
679 |
|
680 |
@trigger_error($message, E_USER_DEPRECATED);
|
681 |
}
|
689 |
|
690 |
protected function getFilterNodeClass($name, $line)
|
691 |
{
|
692 |
+
if (false === $filter = $this->env->getFilter($name)) {
|
693 |
+
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()->getName());
|
694 |
+
$e->addSuggestions($name, array_keys($this->env->getFilters()));
|
|
|
|
|
695 |
|
696 |
throw $e;
|
697 |
}
|
704 |
if ($filter->getAlternative()) {
|
705 |
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
|
706 |
}
|
707 |
+
$message .= sprintf(' in %s at line %d.', $this->parser->getStream()->getSourceContext()->getName(), $line);
|
708 |
|
709 |
@trigger_error($message, E_USER_DEPRECATED);
|
710 |
}
|
library/twig/twig/lib/Twig/Extension.php
CHANGED
@@ -76,4 +76,14 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|
76 |
{
|
77 |
return array();
|
78 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
}
|
76 |
{
|
77 |
return array();
|
78 |
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* {@inheritdoc}
|
82 |
+
*
|
83 |
+
* @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
|
84 |
+
*/
|
85 |
+
public function getName()
|
86 |
+
{
|
87 |
+
return get_class($this);
|
88 |
+
}
|
89 |
}
|
library/twig/twig/lib/Twig/Extension/Core.php
CHANGED
@@ -132,6 +132,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|
132 |
new Twig_TokenParser_Flush(),
|
133 |
new Twig_TokenParser_Do(),
|
134 |
new Twig_TokenParser_Embed(),
|
|
|
135 |
);
|
136 |
}
|
137 |
|
@@ -258,82 +259,14 @@ class Twig_Extension_Core extends Twig_Extension
|
|
258 |
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
259 |
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
260 |
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
261 |
-
'is' => array('precedence' => 100, '
|
262 |
-
'is not' => array('precedence' => 100, '
|
263 |
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
264 |
'??' => array('precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
265 |
),
|
266 |
);
|
267 |
}
|
268 |
|
269 |
-
public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
|
270 |
-
{
|
271 |
-
return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
|
272 |
-
}
|
273 |
-
|
274 |
-
public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
|
275 |
-
{
|
276 |
-
$stream = $parser->getStream();
|
277 |
-
list($name, $test) = $this->getTest($parser, $node->getLine());
|
278 |
-
|
279 |
-
if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
|
280 |
-
$message = sprintf('Twig Test "%s" is deprecated', $name);
|
281 |
-
if (!is_bool($test->getDeprecatedVersion())) {
|
282 |
-
$message .= sprintf(' since version %s', $test->getDeprecatedVersion());
|
283 |
-
}
|
284 |
-
if ($test->getAlternative()) {
|
285 |
-
$message .= sprintf('. Use "%s" instead', $test->getAlternative());
|
286 |
-
}
|
287 |
-
$message .= sprintf(' in %s at line %d.', $stream->getFilename(), $stream->getCurrent()->getLine());
|
288 |
-
|
289 |
-
@trigger_error($message, E_USER_DEPRECATED);
|
290 |
-
}
|
291 |
-
|
292 |
-
$class = $this->getTestNodeClass($parser, $test);
|
293 |
-
$arguments = null;
|
294 |
-
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
295 |
-
$arguments = $parser->getExpressionParser()->parseArguments(true);
|
296 |
-
}
|
297 |
-
|
298 |
-
return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
|
299 |
-
}
|
300 |
-
|
301 |
-
protected function getTest(Twig_Parser $parser, $line)
|
302 |
-
{
|
303 |
-
$stream = $parser->getStream();
|
304 |
-
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
305 |
-
$env = $parser->getEnvironment();
|
306 |
-
|
307 |
-
if ($test = $env->getTest($name)) {
|
308 |
-
return array($name, $test);
|
309 |
-
}
|
310 |
-
|
311 |
-
if ($stream->test(Twig_Token::NAME_TYPE)) {
|
312 |
-
// try 2-words tests
|
313 |
-
$name = $name.' '.$parser->getCurrentToken()->getValue();
|
314 |
-
|
315 |
-
if ($test = $env->getTest($name)) {
|
316 |
-
$parser->getStream()->next();
|
317 |
-
|
318 |
-
return array($name, $test);
|
319 |
-
}
|
320 |
-
}
|
321 |
-
|
322 |
-
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $parser->getFilename());
|
323 |
-
$e->addSuggestions($name, array_keys($env->getTests()));
|
324 |
-
|
325 |
-
throw $e;
|
326 |
-
}
|
327 |
-
|
328 |
-
protected function getTestNodeClass(Twig_Parser $parser, $test)
|
329 |
-
{
|
330 |
-
if ($test instanceof Twig_SimpleTest) {
|
331 |
-
return $test->getNodeClass();
|
332 |
-
}
|
333 |
-
|
334 |
-
return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test';
|
335 |
-
}
|
336 |
-
|
337 |
public function getName()
|
338 |
{
|
339 |
return 'core';
|
@@ -343,7 +276,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|
343 |
/**
|
344 |
* Cycles over a value.
|
345 |
*
|
346 |
-
* @param ArrayAccess|array $values
|
347 |
* @param int $position The cycle position
|
348 |
*
|
349 |
* @return string The next value in the cycle
|
@@ -363,8 +296,8 @@ function twig_cycle($values, $position)
|
|
363 |
* - a random character from a string
|
364 |
* - a random integer between 0 and the integer parameter.
|
365 |
*
|
366 |
-
* @param Twig_Environment
|
367 |
-
* @param Traversable|array|int|string $values The values to pick a random item from
|
368 |
*
|
369 |
* @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
|
370 |
*
|
@@ -423,7 +356,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
423 |
* {{ post.published_at|date("m/d/Y") }}
|
424 |
* </pre>
|
425 |
*
|
426 |
-
* @param Twig_Environment $env
|
427 |
* @param DateTime|DateTimeInterface|DateInterval|string $date A date
|
428 |
* @param string|null $format The target format, null to use the default
|
429 |
* @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged
|
@@ -433,7 +366,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
433 |
function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
|
434 |
{
|
435 |
if (null === $format) {
|
436 |
-
$formats = $env->getExtension('
|
437 |
$format = $date instanceof DateInterval ? $formats[1] : $formats[0];
|
438 |
}
|
439 |
|
@@ -451,7 +384,7 @@ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $
|
|
451 |
* {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
|
452 |
* </pre>
|
453 |
*
|
454 |
-
* @param Twig_Environment $env
|
455 |
* @param DateTime|string $date A date
|
456 |
* @param string $modifier A modifier string
|
457 |
*
|
@@ -477,7 +410,7 @@ function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
|
|
477 |
* {% endif %}
|
478 |
* </pre>
|
479 |
*
|
480 |
-
* @param Twig_Environment $env
|
481 |
* @param DateTime|DateTimeInterface|string|null $date A date
|
482 |
* @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged
|
483 |
*
|
@@ -488,7 +421,7 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
|
|
488 |
// determine the timezone
|
489 |
if (false !== $timezone) {
|
490 |
if (null === $timezone) {
|
491 |
-
$timezone = $env->getExtension('
|
492 |
} elseif (!$timezone instanceof DateTimeZone) {
|
493 |
$timezone = new DateTimeZone($timezone);
|
494 |
}
|
@@ -509,14 +442,14 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
|
|
509 |
}
|
510 |
|
511 |
if (null === $date || 'now' === $date) {
|
512 |
-
return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('
|
513 |
}
|
514 |
|
515 |
$asString = (string) $date;
|
516 |
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
517 |
$date = new DateTime('@'.$date);
|
518 |
} else {
|
519 |
-
$date = new DateTime($date, $env->getExtension('
|
520 |
}
|
521 |
|
522 |
if (false !== $timezone) {
|
@@ -544,7 +477,7 @@ function twig_replace_filter($str, $from, $to = null)
|
|
544 |
|
545 |
return strtr($str, $from, $to);
|
546 |
} elseif (!is_array($from)) {
|
547 |
-
throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".',is_object($from) ? get_class($from) : gettype($from)));
|
548 |
}
|
549 |
|
550 |
return strtr($str, $from);
|
@@ -579,7 +512,7 @@ function twig_round($value, $precision = 0, $method = 'common')
|
|
579 |
* be used. Supplying any of the parameters will override the defaults set in the
|
580 |
* environment object.
|
581 |
*
|
582 |
-
* @param Twig_Environment $env
|
583 |
* @param mixed $number A float/int/string of the number to format
|
584 |
* @param int $decimal The number of decimal points to display.
|
585 |
* @param string $decimalPoint The character(s) to use for the decimal point.
|
@@ -589,7 +522,7 @@ function twig_round($value, $precision = 0, $method = 'common')
|
|
589 |
*/
|
590 |
function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
|
591 |
{
|
592 |
-
$defaults = $env->getExtension('
|
593 |
if (null === $decimal) {
|
594 |
$decimal = $defaults[0];
|
595 |
}
|
@@ -708,7 +641,7 @@ function twig_array_merge($arr1, $arr2)
|
|
708 |
/**
|
709 |
* Slices a variable.
|
710 |
*
|
711 |
-
* @param Twig_Environment $env
|
712 |
* @param mixed $item A variable
|
713 |
* @param int $start Start of the slice
|
714 |
* @param int $length Size of the slice
|
@@ -750,7 +683,7 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese
|
|
750 |
/**
|
751 |
* Returns the first element of the item.
|
752 |
*
|
753 |
-
* @param Twig_Environment $env
|
754 |
* @param mixed $item A variable
|
755 |
*
|
756 |
* @return mixed The first element of the item
|
@@ -765,7 +698,7 @@ function twig_first(Twig_Environment $env, $item)
|
|
765 |
/**
|
766 |
* Returns the last element of the item.
|
767 |
*
|
768 |
-
* @param Twig_Environment $env
|
769 |
* @param mixed $item A variable
|
770 |
*
|
771 |
* @return mixed The last element of the item
|
@@ -821,7 +754,7 @@ function twig_join_filter($value, $glue = '')
|
|
821 |
* {# returns [aa, bb, cc] #}
|
822 |
* </pre>
|
823 |
*
|
824 |
-
* @param Twig_Environment $env
|
825 |
* @param string $value A string
|
826 |
* @param string $delimiter The delimiter
|
827 |
* @param int $limit The limit
|
@@ -901,7 +834,7 @@ function twig_get_array_keys_filter($array)
|
|
901 |
/**
|
902 |
* Reverses a variable.
|
903 |
*
|
904 |
-
* @param Twig_Environment $env
|
905 |
* @param array|Traversable|string $item An array, a Traversable instance, or a string
|
906 |
* @param bool $preserveKeys Whether to preserve key or not
|
907 |
*
|
@@ -977,7 +910,7 @@ function twig_in_filter($value, $compare)
|
|
977 |
/**
|
978 |
* Escapes a string.
|
979 |
*
|
980 |
-
* @param Twig_Environment $env
|
981 |
* @param mixed $string The value to be escaped
|
982 |
* @param string $strategy The escaping strategy
|
983 |
* @param string $charset The charset
|
@@ -1058,7 +991,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1058 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1059 |
}
|
1060 |
|
1061 |
-
if (0 == strlen($string) ? false :
|
1062 |
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
1063 |
}
|
1064 |
|
@@ -1075,7 +1008,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1075 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1076 |
}
|
1077 |
|
1078 |
-
if (0 == strlen($string) ? false :
|
1079 |
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
1080 |
}
|
1081 |
|
@@ -1092,7 +1025,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1092 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1093 |
}
|
1094 |
|
1095 |
-
if (0 == strlen($string) ? false :
|
1096 |
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
1097 |
}
|
1098 |
|
@@ -1115,7 +1048,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1115 |
static $escapers;
|
1116 |
|
1117 |
if (null === $escapers) {
|
1118 |
-
$escapers = $env->getExtension('
|
1119 |
}
|
1120 |
|
1121 |
if (isset($escapers[$strategy])) {
|
@@ -1256,7 +1189,7 @@ if (function_exists('mb_get_info')) {
|
|
1256 |
/**
|
1257 |
* Returns the length of a variable.
|
1258 |
*
|
1259 |
-
* @param Twig_Environment $env
|
1260 |
* @param mixed $thing A variable
|
1261 |
*
|
1262 |
* @return int The length of the value
|
@@ -1269,7 +1202,7 @@ if (function_exists('mb_get_info')) {
|
|
1269 |
/**
|
1270 |
* Converts a string to uppercase.
|
1271 |
*
|
1272 |
-
* @param Twig_Environment $env
|
1273 |
* @param string $string A string
|
1274 |
*
|
1275 |
* @return string The uppercased string
|
@@ -1286,7 +1219,7 @@ if (function_exists('mb_get_info')) {
|
|
1286 |
/**
|
1287 |
* Converts a string to lowercase.
|
1288 |
*
|
1289 |
-
* @param Twig_Environment $env
|
1290 |
* @param string $string A string
|
1291 |
*
|
1292 |
* @return string The lowercased string
|
@@ -1303,7 +1236,7 @@ if (function_exists('mb_get_info')) {
|
|
1303 |
/**
|
1304 |
* Returns a titlecased string.
|
1305 |
*
|
1306 |
-
* @param Twig_Environment $env
|
1307 |
* @param string $string A string
|
1308 |
*
|
1309 |
* @return string The titlecased string
|
@@ -1320,7 +1253,7 @@ if (function_exists('mb_get_info')) {
|
|
1320 |
/**
|
1321 |
* Returns a capitalized string.
|
1322 |
*
|
1323 |
-
* @param Twig_Environment $env
|
1324 |
* @param string $string A string
|
1325 |
*
|
1326 |
* @return string The capitalized string
|
@@ -1339,7 +1272,7 @@ else {
|
|
1339 |
/**
|
1340 |
* Returns the length of a variable.
|
1341 |
*
|
1342 |
-
* @param Twig_Environment $env
|
1343 |
* @param mixed $thing A variable
|
1344 |
*
|
1345 |
* @return int The length of the value
|
@@ -1352,7 +1285,7 @@ else {
|
|
1352 |
/**
|
1353 |
* Returns a titlecased string.
|
1354 |
*
|
1355 |
-
* @param Twig_Environment $env
|
1356 |
* @param string $string A string
|
1357 |
*
|
1358 |
* @return string The titlecased string
|
@@ -1365,7 +1298,7 @@ else {
|
|
1365 |
/**
|
1366 |
* Returns a capitalized string.
|
1367 |
*
|
1368 |
-
* @param Twig_Environment $env
|
1369 |
* @param string $string A string
|
1370 |
*
|
1371 |
* @return string The capitalized string
|
@@ -1451,8 +1384,8 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|
1451 |
$variables = array_merge($context, $variables);
|
1452 |
}
|
1453 |
|
1454 |
-
if ($isSandboxed = $sandboxed && $env->hasExtension('
|
1455 |
-
$sandbox = $env->getExtension('
|
1456 |
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
|
1457 |
$sandbox->enableSandbox();
|
1458 |
}
|
@@ -1489,8 +1422,13 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|
1489 |
*/
|
1490 |
function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
|
1491 |
{
|
|
|
1492 |
try {
|
1493 |
-
|
|
|
|
|
|
|
|
|
1494 |
} catch (Twig_Error_Loader $e) {
|
1495 |
if (!$ignoreMissing) {
|
1496 |
throw $e;
|
@@ -1515,6 +1453,23 @@ function twig_constant($constant, $object = null)
|
|
1515 |
return constant($constant);
|
1516 |
}
|
1517 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1518 |
/**
|
1519 |
* Batches item.
|
1520 |
*
|
132 |
new Twig_TokenParser_Flush(),
|
133 |
new Twig_TokenParser_Do(),
|
134 |
new Twig_TokenParser_Embed(),
|
135 |
+
new Twig_TokenParser_With(),
|
136 |
);
|
137 |
}
|
138 |
|
259 |
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
260 |
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
261 |
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
262 |
+
'is' => array('precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
263 |
+
'is not' => array('precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
264 |
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
265 |
'??' => array('precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
266 |
),
|
267 |
);
|
268 |
}
|
269 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
public function getName()
|
271 |
{
|
272 |
return 'core';
|
276 |
/**
|
277 |
* Cycles over a value.
|
278 |
*
|
279 |
+
* @param ArrayAccess|array $values
|
280 |
* @param int $position The cycle position
|
281 |
*
|
282 |
* @return string The next value in the cycle
|
296 |
* - a random character from a string
|
297 |
* - a random integer between 0 and the integer parameter.
|
298 |
*
|
299 |
+
* @param Twig_Environment $env
|
300 |
+
* @param Traversable|array|int|float|string $values The values to pick a random item from
|
301 |
*
|
302 |
* @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
|
303 |
*
|
356 |
* {{ post.published_at|date("m/d/Y") }}
|
357 |
* </pre>
|
358 |
*
|
359 |
+
* @param Twig_Environment $env
|
360 |
* @param DateTime|DateTimeInterface|DateInterval|string $date A date
|
361 |
* @param string|null $format The target format, null to use the default
|
362 |
* @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged
|
366 |
function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
|
367 |
{
|
368 |
if (null === $format) {
|
369 |
+
$formats = $env->getExtension('Twig_Extension_Core')->getDateFormat();
|
370 |
$format = $date instanceof DateInterval ? $formats[1] : $formats[0];
|
371 |
}
|
372 |
|
384 |
* {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
|
385 |
* </pre>
|
386 |
*
|
387 |
+
* @param Twig_Environment $env
|
388 |
* @param DateTime|string $date A date
|
389 |
* @param string $modifier A modifier string
|
390 |
*
|
410 |
* {% endif %}
|
411 |
* </pre>
|
412 |
*
|
413 |
+
* @param Twig_Environment $env
|
414 |
* @param DateTime|DateTimeInterface|string|null $date A date
|
415 |
* @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged
|
416 |
*
|
421 |
// determine the timezone
|
422 |
if (false !== $timezone) {
|
423 |
if (null === $timezone) {
|
424 |
+
$timezone = $env->getExtension('Twig_Extension_Core')->getTimezone();
|
425 |
} elseif (!$timezone instanceof DateTimeZone) {
|
426 |
$timezone = new DateTimeZone($timezone);
|
427 |
}
|
442 |
}
|
443 |
|
444 |
if (null === $date || 'now' === $date) {
|
445 |
+
return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('Twig_Extension_Core')->getTimezone());
|
446 |
}
|
447 |
|
448 |
$asString = (string) $date;
|
449 |
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
450 |
$date = new DateTime('@'.$date);
|
451 |
} else {
|
452 |
+
$date = new DateTime($date, $env->getExtension('Twig_Extension_Core')->getTimezone());
|
453 |
}
|
454 |
|
455 |
if (false !== $timezone) {
|
477 |
|
478 |
return strtr($str, $from, $to);
|
479 |
} elseif (!is_array($from)) {
|
480 |
+
throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', is_object($from) ? get_class($from) : gettype($from)));
|
481 |
}
|
482 |
|
483 |
return strtr($str, $from);
|
512 |
* be used. Supplying any of the parameters will override the defaults set in the
|
513 |
* environment object.
|
514 |
*
|
515 |
+
* @param Twig_Environment $env
|
516 |
* @param mixed $number A float/int/string of the number to format
|
517 |
* @param int $decimal The number of decimal points to display.
|
518 |
* @param string $decimalPoint The character(s) to use for the decimal point.
|
522 |
*/
|
523 |
function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
|
524 |
{
|
525 |
+
$defaults = $env->getExtension('Twig_Extension_Core')->getNumberFormat();
|
526 |
if (null === $decimal) {
|
527 |
$decimal = $defaults[0];
|
528 |
}
|
641 |
/**
|
642 |
* Slices a variable.
|
643 |
*
|
644 |
+
* @param Twig_Environment $env
|
645 |
* @param mixed $item A variable
|
646 |
* @param int $start Start of the slice
|
647 |
* @param int $length Size of the slice
|
683 |
/**
|
684 |
* Returns the first element of the item.
|
685 |
*
|
686 |
+
* @param Twig_Environment $env
|
687 |
* @param mixed $item A variable
|
688 |
*
|
689 |
* @return mixed The first element of the item
|
698 |
/**
|
699 |
* Returns the last element of the item.
|
700 |
*
|
701 |
+
* @param Twig_Environment $env
|
702 |
* @param mixed $item A variable
|
703 |
*
|
704 |
* @return mixed The last element of the item
|
754 |
* {# returns [aa, bb, cc] #}
|
755 |
* </pre>
|
756 |
*
|
757 |
+
* @param Twig_Environment $env
|
758 |
* @param string $value A string
|
759 |
* @param string $delimiter The delimiter
|
760 |
* @param int $limit The limit
|
834 |
/**
|
835 |
* Reverses a variable.
|
836 |
*
|
837 |
+
* @param Twig_Environment $env
|
838 |
* @param array|Traversable|string $item An array, a Traversable instance, or a string
|
839 |
* @param bool $preserveKeys Whether to preserve key or not
|
840 |
*
|
910 |
/**
|
911 |
* Escapes a string.
|
912 |
*
|
913 |
+
* @param Twig_Environment $env
|
914 |
* @param mixed $string The value to be escaped
|
915 |
* @param string $strategy The escaping strategy
|
916 |
* @param string $charset The charset
|
991 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
992 |
}
|
993 |
|
994 |
+
if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) {
|
995 |
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
996 |
}
|
997 |
|
1008 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1009 |
}
|
1010 |
|
1011 |
+
if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) {
|
1012 |
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
1013 |
}
|
1014 |
|
1025 |
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
1026 |
}
|
1027 |
|
1028 |
+
if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) {
|
1029 |
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
1030 |
}
|
1031 |
|
1048 |
static $escapers;
|
1049 |
|
1050 |
if (null === $escapers) {
|
1051 |
+
$escapers = $env->getExtension('Twig_Extension_Core')->getEscapers();
|
1052 |
}
|
1053 |
|
1054 |
if (isset($escapers[$strategy])) {
|
1189 |
/**
|
1190 |
* Returns the length of a variable.
|
1191 |
*
|
1192 |
+
* @param Twig_Environment $env
|
1193 |
* @param mixed $thing A variable
|
1194 |
*
|
1195 |
* @return int The length of the value
|
1202 |
/**
|
1203 |
* Converts a string to uppercase.
|
1204 |
*
|
1205 |
+
* @param Twig_Environment $env
|
1206 |
* @param string $string A string
|
1207 |
*
|
1208 |
* @return string The uppercased string
|
1219 |
/**
|
1220 |
* Converts a string to lowercase.
|
1221 |
*
|
1222 |
+
* @param Twig_Environment $env
|
1223 |
* @param string $string A string
|
1224 |
*
|
1225 |
* @return string The lowercased string
|
1236 |
/**
|
1237 |
* Returns a titlecased string.
|
1238 |
*
|
1239 |
+
* @param Twig_Environment $env
|
1240 |
* @param string $string A string
|
1241 |
*
|
1242 |
* @return string The titlecased string
|
1253 |
/**
|
1254 |
* Returns a capitalized string.
|
1255 |
*
|
1256 |
+
* @param Twig_Environment $env
|
1257 |
* @param string $string A string
|
1258 |
*
|
1259 |
* @return string The capitalized string
|
1272 |
/**
|
1273 |
* Returns the length of a variable.
|
1274 |
*
|
1275 |
+
* @param Twig_Environment $env
|
1276 |
* @param mixed $thing A variable
|
1277 |
*
|
1278 |
* @return int The length of the value
|
1285 |
/**
|
1286 |
* Returns a titlecased string.
|
1287 |
*
|
1288 |
+
* @param Twig_Environment $env
|
1289 |
* @param string $string A string
|
1290 |
*
|
1291 |
* @return string The titlecased string
|
1298 |
/**
|
1299 |
* Returns a capitalized string.
|
1300 |
*
|
1301 |
+
* @param Twig_Environment $env
|
1302 |
* @param string $string A string
|
1303 |
*
|
1304 |
* @return string The capitalized string
|
1384 |
$variables = array_merge($context, $variables);
|
1385 |
}
|
1386 |
|
1387 |
+
if ($isSandboxed = $sandboxed && $env->hasExtension('Twig_Extension_Sandbox')) {
|
1388 |
+
$sandbox = $env->getExtension('Twig_Extension_Sandbox');
|
1389 |
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
|
1390 |
$sandbox->enableSandbox();
|
1391 |
}
|
1422 |
*/
|
1423 |
function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
|
1424 |
{
|
1425 |
+
$loader = $env->getLoader();
|
1426 |
try {
|
1427 |
+
if (!$loader instanceof Twig_SourceContextLoaderInterface) {
|
1428 |
+
return $loader->getSource($name);
|
1429 |
+
} else {
|
1430 |
+
return $loader->getSourceContext($name)->getCode();
|
1431 |
+
}
|
1432 |
} catch (Twig_Error_Loader $e) {
|
1433 |
if (!$ignoreMissing) {
|
1434 |
throw $e;
|
1453 |
return constant($constant);
|
1454 |
}
|
1455 |
|
1456 |
+
/**
|
1457 |
+
* Checks if a constant exists.
|
1458 |
+
*
|
1459 |
+
* @param string $constant The name of the constant
|
1460 |
+
* @param null|object $object The object to get the constant from
|
1461 |
+
*
|
1462 |
+
* @return bool
|
1463 |
+
*/
|
1464 |
+
function twig_constant_is_defined($constant, $object = null)
|
1465 |
+
{
|
1466 |
+
if (null !== $object) {
|
1467 |
+
$constant = get_class($object).'::'.$constant;
|
1468 |
+
}
|
1469 |
+
|
1470 |
+
return defined($constant);
|
1471 |
+
}
|
1472 |
+
|
1473 |
/**
|
1474 |
* Batches item.
|
1475 |
*
|
library/twig/twig/lib/Twig/Extension/Escaper.php
CHANGED
@@ -13,8 +13,6 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
13 |
protected $defaultStrategy;
|
14 |
|
15 |
/**
|
16 |
-
* Constructor.
|
17 |
-
*
|
18 |
* @param string|false|callable $defaultStrategy An escaping strategy
|
19 |
*
|
20 |
* @see setDefaultStrategy()
|
@@ -45,7 +43,7 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
45 |
* Sets the default strategy to use when not defined by the user.
|
46 |
*
|
47 |
* The strategy can be a valid PHP callback that takes the template
|
48 |
-
*
|
49 |
*
|
50 |
* @param string|false|callable $defaultStrategy An escaping strategy
|
51 |
*/
|
@@ -59,6 +57,12 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
59 |
}
|
60 |
|
61 |
if ('filename' === $defaultStrategy) {
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
$defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess');
|
63 |
}
|
64 |
|
@@ -68,16 +72,16 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
68 |
/**
|
69 |
* Gets the default strategy to use when not defined by the user.
|
70 |
*
|
71 |
-
* @param string $
|
72 |
*
|
73 |
* @return string|false The default strategy to use for the template
|
74 |
*/
|
75 |
-
public function getDefaultStrategy($
|
76 |
{
|
77 |
// disable string callables to avoid calling a function named html or js,
|
78 |
// or any other upcoming escaping strategy
|
79 |
if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
|
80 |
-
return call_user_func($this->defaultStrategy, $
|
81 |
}
|
82 |
|
83 |
return $this->defaultStrategy;
|
13 |
protected $defaultStrategy;
|
14 |
|
15 |
/**
|
|
|
|
|
16 |
* @param string|false|callable $defaultStrategy An escaping strategy
|
17 |
*
|
18 |
* @see setDefaultStrategy()
|
43 |
* Sets the default strategy to use when not defined by the user.
|
44 |
*
|
45 |
* The strategy can be a valid PHP callback that takes the template
|
46 |
+
* name as an argument and returns the strategy to use.
|
47 |
*
|
48 |
* @param string|false|callable $defaultStrategy An escaping strategy
|
49 |
*/
|
57 |
}
|
58 |
|
59 |
if ('filename' === $defaultStrategy) {
|
60 |
+
@trigger_error('Using "filename" as the default strategy is deprecated since version 1.27. Use "name" instead.', E_USER_DEPRECATED);
|
61 |
+
|
62 |
+
$defaultStrategy = 'name';
|
63 |
+
}
|
64 |
+
|
65 |
+
if ('name' === $defaultStrategy) {
|
66 |
$defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess');
|
67 |
}
|
68 |
|
72 |
/**
|
73 |
* Gets the default strategy to use when not defined by the user.
|
74 |
*
|
75 |
+
* @param string $name The template name
|
76 |
*
|
77 |
* @return string|false The default strategy to use for the template
|
78 |
*/
|
79 |
+
public function getDefaultStrategy($name)
|
80 |
{
|
81 |
// disable string callables to avoid calling a function named html or js,
|
82 |
// or any other upcoming escaping strategy
|
83 |
if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
|
84 |
+
return call_user_func($this->defaultStrategy, $name);
|
85 |
}
|
86 |
|
87 |
return $this->defaultStrategy;
|
library/twig/twig/lib/Twig/Extension/Profiler.php
CHANGED
@@ -36,7 +36,7 @@ class Twig_Extension_Profiler extends Twig_Extension
|
|
36 |
|
37 |
public function getNodeVisitors()
|
38 |
{
|
39 |
-
return array(new Twig_Profiler_NodeVisitor_Profiler($this
|
40 |
}
|
41 |
|
42 |
public function getName()
|
36 |
|
37 |
public function getNodeVisitors()
|
38 |
{
|
39 |
+
return array(new Twig_Profiler_NodeVisitor_Profiler(get_class($this)));
|
40 |
}
|
41 |
|
42 |
public function getName()
|
library/twig/twig/lib/Twig/Extension/StringLoader.php
CHANGED
@@ -33,7 +33,7 @@ class Twig_Extension_StringLoader extends Twig_Extension
|
|
33 |
* @param Twig_Environment $env A Twig_Environment instance
|
34 |
* @param string $template A template as a string or object implementing __toString()
|
35 |
*
|
36 |
-
* @return Twig_Template
|
37 |
*/
|
38 |
function twig_template_from_string(Twig_Environment $env, $template)
|
39 |
{
|
33 |
* @param Twig_Environment $env A Twig_Environment instance
|
34 |
* @param string $template A template as a string or object implementing __toString()
|
35 |
*
|
36 |
+
* @return Twig_Template
|
37 |
*/
|
38 |
function twig_template_from_string(Twig_Environment $env, $template)
|
39 |
{
|
library/twig/twig/lib/Twig/ExtensionInterface.php
CHANGED
@@ -21,8 +21,6 @@ interface Twig_ExtensionInterface
|
|
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 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
27 |
*/
|
28 |
public function initRuntime(Twig_Environment $environment);
|
@@ -37,7 +35,7 @@ interface Twig_ExtensionInterface
|
|
37 |
/**
|
38 |
* Returns the node visitor instances to add to the existing list.
|
39 |
*
|
40 |
-
* @return Twig_NodeVisitorInterface[]
|
41 |
*/
|
42 |
public function getNodeVisitors();
|
43 |
|
@@ -82,6 +80,8 @@ interface Twig_ExtensionInterface
|
|
82 |
* Returns the name of the extension.
|
83 |
*
|
84 |
* @return string The extension name
|
|
|
|
|
85 |
*/
|
86 |
public function getName();
|
87 |
}
|
21 |
*
|
22 |
* This is where you can load some file that contains filter functions for instance.
|
23 |
*
|
|
|
|
|
24 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
25 |
*/
|
26 |
public function initRuntime(Twig_Environment $environment);
|
35 |
/**
|
36 |
* Returns the node visitor instances to add to the existing list.
|
37 |
*
|
38 |
+
* @return Twig_NodeVisitorInterface[]
|
39 |
*/
|
40 |
public function getNodeVisitors();
|
41 |
|
80 |
* Returns the name of the extension.
|
81 |
*
|
82 |
* @return string The extension name
|
83 |
+
*
|
84 |
+
* @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
|
85 |
*/
|
86 |
public function getName();
|
87 |
}
|
library/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
CHANGED
@@ -13,7 +13,7 @@
|
|
13 |
* Default autoescaping strategy based on file names.
|
14 |
*
|
15 |
* This strategy sets the HTML as the default autoescaping strategy,
|
16 |
-
* but changes it based on the
|
17 |
*
|
18 |
* Note that there is no runtime performance impact as the
|
19 |
* default autoescaping strategy is set at compilation time.
|
@@ -25,21 +25,21 @@ class Twig_FileExtensionEscapingStrategy
|
|
25 |
/**
|
26 |
* Guesses the best autoescaping strategy based on the file name.
|
27 |
*
|
28 |
-
* @param string $
|
29 |
*
|
30 |
* @return string|false The escaping strategy name to use or false to disable
|
31 |
*/
|
32 |
-
public static function guess($
|
33 |
{
|
34 |
-
if (in_array(substr($
|
35 |
return 'html'; // return html for directories
|
36 |
}
|
37 |
|
38 |
-
if ('.twig' === substr($
|
39 |
-
$
|
40 |
}
|
41 |
|
42 |
-
$extension = pathinfo($
|
43 |
|
44 |
switch ($extension) {
|
45 |
case 'js':
|
13 |
* Default autoescaping strategy based on file names.
|
14 |
*
|
15 |
* This strategy sets the HTML as the default autoescaping strategy,
|
16 |
+
* but changes it based on the template name.
|
17 |
*
|
18 |
* Note that there is no runtime performance impact as the
|
19 |
* default autoescaping strategy is set at compilation time.
|
25 |
/**
|
26 |
* Guesses the best autoescaping strategy based on the file name.
|
27 |
*
|
28 |
+
* @param string $name The template name
|
29 |
*
|
30 |
* @return string|false The escaping strategy name to use or false to disable
|
31 |
*/
|
32 |
+
public static function guess($name)
|
33 |
{
|
34 |
+
if (in_array(substr($name, -1), array('/', '\\'))) {
|
35 |
return 'html'; // return html for directories
|
36 |
}
|
37 |
|
38 |
+
if ('.twig' === substr($name, -5)) {
|
39 |
+
$name = substr($name, 0, -5);
|
40 |
}
|
41 |
|
42 |
+
$extension = pathinfo($name, PATHINFO_EXTENSION);
|
43 |
|
44 |
switch ($extension) {
|
45 |
case 'js':
|
library/twig/twig/lib/Twig/Filter/Method.php
CHANGED
@@ -37,6 +37,6 @@ class Twig_Filter_Method extends Twig_Filter
|
|
37 |
|
38 |
public function compile()
|
39 |
{
|
40 |
-
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension
|
41 |
}
|
42 |
}
|
37 |
|
38 |
public function compile()
|
39 |
{
|
40 |
+
return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
|
41 |
}
|
42 |
}
|
library/twig/twig/lib/Twig/Function/Method.php
CHANGED
@@ -38,6 +38,6 @@ class Twig_Function_Method extends Twig_Function
|
|
38 |
|
39 |
public function compile()
|
40 |
{
|
41 |
-
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension
|
42 |
}
|
43 |
}
|
38 |
|
39 |
public function compile()
|
40 |
{
|
41 |
+
return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
|
42 |
}
|
43 |
}
|
library/twig/twig/lib/Twig/Lexer.php
CHANGED
@@ -26,6 +26,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
26 |
protected $states;
|
27 |
protected $brackets;
|
28 |
protected $env;
|
|
|
29 |
protected $filename;
|
30 |
protected $options;
|
31 |
protected $regexes;
|
@@ -75,8 +76,15 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
75 |
/**
|
76 |
* {@inheritdoc}
|
77 |
*/
|
78 |
-
public function tokenize($code, $
|
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');
|
@@ -84,8 +92,8 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
84 |
$mbEncoding = null;
|
85 |
}
|
86 |
|
87 |
-
$this->code = str_replace(array("\r\n", "\r"), "\n", $
|
88 |
-
$this->filename = $
|
89 |
$this->cursor = 0;
|
90 |
$this->lineno = 1;
|
91 |
$this->end = strlen($this->code);
|
@@ -136,7 +144,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
136 |
mb_internal_encoding($mbEncoding);
|
137 |
}
|
138 |
|
139 |
-
return new Twig_TokenStream($this->tokens, $
|
140 |
}
|
141 |
|
142 |
protected function lexData()
|
@@ -403,7 +411,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
403 |
protected function popState()
|
404 |
{
|
405 |
if (0 === count($this->states)) {
|
406 |
-
throw new Exception('Cannot pop state without a previous state');
|
407 |
}
|
408 |
|
409 |
$this->state = array_pop($this->states);
|
26 |
protected $states;
|
27 |
protected $brackets;
|
28 |
protected $env;
|
29 |
+
// to be renamed to $name in 2.0 (where it is private)
|
30 |
protected $filename;
|
31 |
protected $options;
|
32 |
protected $regexes;
|
76 |
/**
|
77 |
* {@inheritdoc}
|
78 |
*/
|
79 |
+
public function tokenize($code, $name = null)
|
80 |
{
|
81 |
+
if (!$code instanceof Twig_Source) {
|
82 |
+
@trigger_error(sprintf('Passing a string as the $code argument of %s() is deprecated since version 1.27 and will be removed in 2.0. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
|
83 |
+
$source = new Twig_Source($code, $name);
|
84 |
+
} else {
|
85 |
+
$source = $code;
|
86 |
+
}
|
87 |
+
|
88 |
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
|
89 |
$mbEncoding = mb_internal_encoding();
|
90 |
mb_internal_encoding('ASCII');
|
92 |
$mbEncoding = null;
|
93 |
}
|
94 |
|
95 |
+
$this->code = str_replace(array("\r\n", "\r"), "\n", $source->getCode());
|
96 |
+
$this->filename = $source->getName();
|
97 |
$this->cursor = 0;
|
98 |
$this->lineno = 1;
|
99 |
$this->end = strlen($this->code);
|
144 |
mb_internal_encoding($mbEncoding);
|
145 |
}
|
146 |
|
147 |
+
return new Twig_TokenStream($this->tokens, $source);
|
148 |
}
|
149 |
|
150 |
protected function lexData()
|
411 |
protected function popState()
|
412 |
{
|
413 |
if (0 === count($this->states)) {
|
414 |
+
throw new Exception('Cannot pop state without a previous state.');
|
415 |
}
|
416 |
|
417 |
$this->state = array_pop($this->states);
|
library/twig/twig/lib/Twig/LexerInterface.php
CHANGED
@@ -21,12 +21,12 @@ interface Twig_LexerInterface
|
|
21 |
/**
|
22 |
* Tokenizes a source code.
|
23 |
*
|
24 |
-
* @param string $code
|
25 |
-
* @param string
|
26 |
*
|
27 |
-
* @return Twig_TokenStream
|
28 |
*
|
29 |
* @throws Twig_Error_Syntax When the code is syntactically wrong
|
30 |
*/
|
31 |
-
public function tokenize($code, $
|
32 |
}
|
21 |
/**
|
22 |
* Tokenizes a source code.
|
23 |
*
|
24 |
+
* @param string|Twig_Source $code The source code
|
25 |
+
* @param string $name A unique identifier for the source code
|
26 |
*
|
27 |
+
* @return Twig_TokenStream
|
28 |
*
|
29 |
* @throws Twig_Error_Syntax When the code is syntactically wrong
|
30 |
*/
|
31 |
+
public function tokenize($code, $name = null);
|
32 |
}
|
library/twig/twig/lib/Twig/Loader/Array.php
CHANGED
@@ -21,16 +21,14 @@
|
|
21 |
*
|
22 |
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
-
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
25 |
{
|
26 |
protected $templates = array();
|
27 |
|
28 |
/**
|
29 |
-
* Constructor.
|
30 |
-
*
|
31 |
* @param array $templates An array of templates (keys are the names, and values are the source code)
|
32 |
*/
|
33 |
-
public function __construct(array $templates)
|
34 |
{
|
35 |
$this->templates = $templates;
|
36 |
}
|
@@ -51,6 +49,8 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
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));
|
@@ -59,6 +59,19 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
59 |
return $this->templates[$name];
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
/**
|
63 |
* {@inheritdoc}
|
64 |
*/
|
21 |
*
|
22 |
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
+
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
25 |
{
|
26 |
protected $templates = array();
|
27 |
|
28 |
/**
|
|
|
|
|
29 |
* @param array $templates An array of templates (keys are the names, and values are the source code)
|
30 |
*/
|
31 |
+
public function __construct(array $templates = array())
|
32 |
{
|
33 |
$this->templates = $templates;
|
34 |
}
|
49 |
*/
|
50 |
public function getSource($name)
|
51 |
{
|
52 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
53 |
+
|
54 |
$name = (string) $name;
|
55 |
if (!isset($this->templates[$name])) {
|
56 |
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
59 |
return $this->templates[$name];
|
60 |
}
|
61 |
|
62 |
+
/**
|
63 |
+
* {@inheritdoc}
|
64 |
+
*/
|
65 |
+
public function getSourceContext($name)
|
66 |
+
{
|
67 |
+
$name = (string) $name;
|
68 |
+
if (!isset($this->templates[$name])) {
|
69 |
+
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
|
70 |
+
}
|
71 |
+
|
72 |
+
return new Twig_Source($this->templates[$name], $name);
|
73 |
+
}
|
74 |
+
|
75 |
/**
|
76 |
* {@inheritdoc}
|
77 |
*/
|
library/twig/twig/lib/Twig/Loader/Chain.php
CHANGED
@@ -14,15 +14,13 @@
|
|
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 |
-
*
|
24 |
-
*
|
25 |
-
* @param Twig_LoaderInterface[] $loaders An array of loader instances
|
26 |
*/
|
27 |
public function __construct(array $loaders = array())
|
28 |
{
|
@@ -31,11 +29,6 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
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;
|
@@ -47,6 +40,8 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
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)) {
|
@@ -63,6 +58,31 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
63 |
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
64 |
}
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
/**
|
67 |
* {@inheritdoc}
|
68 |
*/
|
@@ -84,7 +104,11 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
84 |
}
|
85 |
|
86 |
try {
|
87 |
-
$loader
|
|
|
|
|
|
|
|
|
88 |
|
89 |
return $this->hasSourceCache[$name] = true;
|
90 |
} catch (Twig_Error_Loader $e) {
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
+
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
18 |
{
|
19 |
private $hasSourceCache = array();
|
20 |
protected $loaders = array();
|
21 |
|
22 |
/**
|
23 |
+
* @param Twig_LoaderInterface[] $loaders
|
|
|
|
|
24 |
*/
|
25 |
public function __construct(array $loaders = array())
|
26 |
{
|
29 |
}
|
30 |
}
|
31 |
|
|
|
|
|
|
|
|
|
|
|
32 |
public function addLoader(Twig_LoaderInterface $loader)
|
33 |
{
|
34 |
$this->loaders[] = $loader;
|
40 |
*/
|
41 |
public function getSource($name)
|
42 |
{
|
43 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
44 |
+
|
45 |
$exceptions = array();
|
46 |
foreach ($this->loaders as $loader) {
|
47 |
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
58 |
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
59 |
}
|
60 |
|
61 |
+
/**
|
62 |
+
* {@inheritdoc}
|
63 |
+
*/
|
64 |
+
public function getSourceContext($name)
|
65 |
+
{
|
66 |
+
$exceptions = array();
|
67 |
+
foreach ($this->loaders as $loader) {
|
68 |
+
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
69 |
+
continue;
|
70 |
+
}
|
71 |
+
|
72 |
+
try {
|
73 |
+
if ($loader instanceof Twig_SourceContextLoaderInterface) {
|
74 |
+
return $loader->getSourceContext($name);
|
75 |
+
}
|
76 |
+
|
77 |
+
return new Twig_Source($loader->getSource($name), $name);
|
78 |
+
} catch (Twig_Error_Loader $e) {
|
79 |
+
$exceptions[] = $e->getMessage();
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
84 |
+
}
|
85 |
+
|
86 |
/**
|
87 |
* {@inheritdoc}
|
88 |
*/
|
104 |
}
|
105 |
|
106 |
try {
|
107 |
+
if ($loader instanceof Twig_SourceContextLoaderInterface) {
|
108 |
+
$loader->getSourceContext($name);
|
109 |
+
} else {
|
110 |
+
$loader->getSource($name);
|
111 |
+
}
|
112 |
|
113 |
return $this->hasSourceCache[$name] = true;
|
114 |
} catch (Twig_Error_Loader $e) {
|
library/twig/twig/lib/Twig/Loader/Filesystem.php
CHANGED
@@ -14,7 +14,7 @@
|
|
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__';
|
@@ -23,13 +23,19 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
23 |
protected $cache = array();
|
24 |
protected $errorCache = array();
|
25 |
|
|
|
|
|
26 |
/**
|
27 |
-
*
|
28 |
-
*
|
29 |
-
* @param string|array $paths A path or an array of paths where to look for templates
|
30 |
*/
|
31 |
-
public function __construct($paths = array())
|
32 |
{
|
|
|
|
|
|
|
|
|
|
|
33 |
if ($paths) {
|
34 |
$this->setPaths($paths);
|
35 |
}
|
@@ -81,7 +87,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
81 |
* Adds a path where templates are stored.
|
82 |
*
|
83 |
* @param string $path A path where to look for templates
|
84 |
-
* @param string $namespace A path
|
85 |
*
|
86 |
* @throws Twig_Error_Loader
|
87 |
*/
|
@@ -90,8 +96,9 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
90 |
// invalidate the cache
|
91 |
$this->cache = $this->errorCache = array();
|
92 |
|
93 |
-
|
94 |
-
|
|
|
95 |
}
|
96 |
|
97 |
$this->paths[$namespace][] = rtrim($path, '/\\');
|
@@ -101,7 +108,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
101 |
* Prepends a path where templates are stored.
|
102 |
*
|
103 |
* @param string $path A path where to look for templates
|
104 |
-
* @param string $namespace A path
|
105 |
*
|
106 |
* @throws Twig_Error_Loader
|
107 |
*/
|
@@ -110,8 +117,9 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
110 |
// invalidate the cache
|
111 |
$this->cache = $this->errorCache = array();
|
112 |
|
113 |
-
|
114 |
-
|
|
|
115 |
}
|
116 |
|
117 |
$path = rtrim($path, '/\\');
|
@@ -128,15 +136,33 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
128 |
*/
|
129 |
public function getSource($name)
|
130 |
{
|
|
|
|
|
131 |
return file_get_contents($this->findTemplate($name));
|
132 |
}
|
133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
/**
|
135 |
* {@inheritdoc}
|
136 |
*/
|
137 |
public function getCacheKey($name)
|
138 |
{
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
141 |
|
142 |
/**
|
@@ -153,6 +179,8 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
153 |
try {
|
154 |
return false !== $this->findTemplate($name, false);
|
155 |
} catch (Twig_Error_Loader $exception) {
|
|
|
|
|
156 |
return false;
|
157 |
}
|
158 |
}
|
@@ -197,8 +225,16 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
197 |
}
|
198 |
|
199 |
foreach ($this->paths[$namespace] as $path) {
|
|
|
|
|
|
|
|
|
200 |
if (is_file($path.'/'.$shortname)) {
|
201 |
-
|
|
|
|
|
|
|
|
|
202 |
}
|
203 |
}
|
204 |
|
@@ -254,18 +290,14 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
254 |
}
|
255 |
}
|
256 |
|
257 |
-
private function
|
258 |
{
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
}
|
267 |
-
}
|
268 |
-
|
269 |
-
return implode('/', $new);
|
270 |
}
|
271 |
}
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
+
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
18 |
{
|
19 |
/** Identifier of the main namespace. */
|
20 |
const MAIN_NAMESPACE = '__main__';
|
23 |
protected $cache = array();
|
24 |
protected $errorCache = array();
|
25 |
|
26 |
+
private $rootPath;
|
27 |
+
|
28 |
/**
|
29 |
+
* @param string|array $paths A path or an array of paths where to look for templates
|
30 |
+
* @param string|null $rootPath The root path common to all relative paths (null for getcwd())
|
|
|
31 |
*/
|
32 |
+
public function __construct($paths = array(), $rootPath = null)
|
33 |
{
|
34 |
+
$this->rootPath = (null === $rootPath ? getcwd() : $rootPath).DIRECTORY_SEPARATOR;
|
35 |
+
if (false !== $realPath = realpath($rootPath)) {
|
36 |
+
$this->rootPath = $realPath.DIRECTORY_SEPARATOR;
|
37 |
+
}
|
38 |
+
|
39 |
if ($paths) {
|
40 |
$this->setPaths($paths);
|
41 |
}
|
87 |
* Adds a path where templates are stored.
|
88 |
*
|
89 |
* @param string $path A path where to look for templates
|
90 |
+
* @param string $namespace A path namespace
|
91 |
*
|
92 |
* @throws Twig_Error_Loader
|
93 |
*/
|
96 |
// invalidate the cache
|
97 |
$this->cache = $this->errorCache = array();
|
98 |
|
99 |
+
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
100 |
+
if (!is_dir($checkPath)) {
|
101 |
+
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
|
102 |
}
|
103 |
|
104 |
$this->paths[$namespace][] = rtrim($path, '/\\');
|
108 |
* Prepends a path where templates are stored.
|
109 |
*
|
110 |
* @param string $path A path where to look for templates
|
111 |
+
* @param string $namespace A path namespace
|
112 |
*
|
113 |
* @throws Twig_Error_Loader
|
114 |
*/
|
117 |
// invalidate the cache
|
118 |
$this->cache = $this->errorCache = array();
|
119 |
|
120 |
+
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
121 |
+
if (!is_dir($checkPath)) {
|
122 |
+
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
|
123 |
}
|
124 |
|
125 |
$path = rtrim($path, '/\\');
|
136 |
*/
|
137 |
public function getSource($name)
|
138 |
{
|
139 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
140 |
+
|
141 |
return file_get_contents($this->findTemplate($name));
|
142 |
}
|
143 |
|
144 |
+
/**
|
145 |
+
* {@inheritdoc}
|
146 |
+
*/
|
147 |
+
public function getSourceContext($name)
|
148 |
+
{
|
149 |
+
$path = $this->findTemplate($name);
|
150 |
+
|
151 |
+
return new Twig_Source(file_get_contents($path), $name, $path);
|
152 |
+
}
|
153 |
+
|
154 |
/**
|
155 |
* {@inheritdoc}
|
156 |
*/
|
157 |
public function getCacheKey($name)
|
158 |
{
|
159 |
+
$path = $this->findTemplate($name);
|
160 |
+
$len = strlen($this->rootPath);
|
161 |
+
if (0 === strncmp($this->rootPath, $path, $len)) {
|
162 |
+
return substr($path, $len);
|
163 |
+
}
|
164 |
+
|
165 |
+
return $path;
|
166 |
}
|
167 |
|
168 |
/**
|
179 |
try {
|
180 |
return false !== $this->findTemplate($name, false);
|
181 |
} catch (Twig_Error_Loader $exception) {
|
182 |
+
@trigger_error(sprintf('In %s::findTemplate(), you must accept a second argument that when set to "false" returns "false" instead of throwing an exception. Not supporting this argument is deprecated since version 1.27.', get_class($this)), E_USER_DEPRECATED);
|
183 |
+
|
184 |
return false;
|
185 |
}
|
186 |
}
|
225 |
}
|
226 |
|
227 |
foreach ($this->paths[$namespace] as $path) {
|
228 |
+
if (!$this->isAbsolutePath($path)) {
|
229 |
+
$path = $this->rootPath.'/'.$path;
|
230 |
+
}
|
231 |
+
|
232 |
if (is_file($path.'/'.$shortname)) {
|
233 |
+
if (false !== $realpath = realpath($path.'/'.$shortname)) {
|
234 |
+
return $this->cache[$name] = $realpath;
|
235 |
+
}
|
236 |
+
|
237 |
+
return $this->cache[$name] = $path.'/'.$shortname;
|
238 |
}
|
239 |
}
|
240 |
|
290 |
}
|
291 |
}
|
292 |
|
293 |
+
private function isAbsolutePath($file)
|
294 |
{
|
295 |
+
return strspn($file, '/\\', 0, 1)
|
296 |
+
|| (strlen($file) > 3 && ctype_alpha($file[0])
|
297 |
+
&& substr($file, 1, 1) === ':'
|
298 |
+
&& strspn($file, '/\\', 2, 1)
|
299 |
+
)
|
300 |
+
|| null !== parse_url($file, PHP_URL_SCHEME)
|
301 |
+
;
|
|
|
|
|
|
|
|
|
302 |
}
|
303 |
}
|
library/twig/twig/lib/Twig/Loader/String.php
CHANGED
@@ -27,16 +27,26 @@
|
|
27 |
*
|
28 |
* @author Fabien Potencier <fabien@symfony.com>
|
29 |
*/
|
30 |
-
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
31 |
{
|
32 |
/**
|
33 |
* {@inheritdoc}
|
34 |
*/
|
35 |
public function getSource($name)
|
36 |
{
|
|
|
|
|
37 |
return $name;
|
38 |
}
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
/**
|
41 |
* {@inheritdoc}
|
42 |
*/
|
27 |
*
|
28 |
* @author Fabien Potencier <fabien@symfony.com>
|
29 |
*/
|
30 |
+
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
31 |
{
|
32 |
/**
|
33 |
* {@inheritdoc}
|
34 |
*/
|
35 |
public function getSource($name)
|
36 |
{
|
37 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
|
38 |
+
|
39 |
return $name;
|
40 |
}
|
41 |
|
42 |
+
/**
|
43 |
+
* {@inheritdoc}
|
44 |
+
*/
|
45 |
+
public function getSourceContext($name)
|
46 |
+
{
|
47 |
+
return new Twig_Source($name, $name);
|
48 |
+
}
|
49 |
+
|
50 |
/**
|
51 |
* {@inheritdoc}
|
52 |
*/
|
library/twig/twig/lib/Twig/LoaderInterface.php
CHANGED
@@ -24,6 +24,8 @@ interface Twig_LoaderInterface
|
|
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 |
|
24 |
* @return string The template source code
|
25 |
*
|
26 |
* @throws Twig_Error_Loader When $name is not found
|
27 |
+
*
|
28 |
+
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
|
29 |
*/
|
30 |
public function getSource($name);
|
31 |
|
library/twig/twig/lib/Twig/Node.php
CHANGED
@@ -22,7 +22,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
22 |
protected $lineno;
|
23 |
protected $tag;
|
24 |
|
25 |
-
private $
|
26 |
|
27 |
/**
|
28 |
* Constructor.
|
@@ -118,8 +118,18 @@ class Twig_Node implements Twig_NodeInterface
|
|
118 |
}
|
119 |
}
|
120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
public function getLine()
|
122 |
{
|
|
|
|
|
123 |
return $this->lineno;
|
124 |
}
|
125 |
|
@@ -129,11 +139,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
129 |
}
|
130 |
|
131 |
/**
|
132 |
-
*
|
133 |
-
*
|
134 |
-
* @param string $name The attribute name
|
135 |
-
*
|
136 |
-
* @return bool true if the attribute is defined, false otherwise
|
137 |
*/
|
138 |
public function hasAttribute($name)
|
139 |
{
|
@@ -141,10 +147,6 @@ class Twig_Node implements Twig_NodeInterface
|
|
141 |
}
|
142 |
|
143 |
/**
|
144 |
-
* Gets an attribute value by name.
|
145 |
-
*
|
146 |
-
* @param string $name
|
147 |
-
*
|
148 |
* @return mixed
|
149 |
*/
|
150 |
public function getAttribute($name)
|
@@ -157,8 +159,6 @@ class Twig_Node implements Twig_NodeInterface
|
|
157 |
}
|
158 |
|
159 |
/**
|
160 |
-
* Sets an attribute by name to a value.
|
161 |
-
*
|
162 |
* @param string $name
|
163 |
* @param mixed $value
|
164 |
*/
|
@@ -167,21 +167,12 @@ class Twig_Node implements Twig_NodeInterface
|
|
167 |
$this->attributes[$name] = $value;
|
168 |
}
|
169 |
|
170 |
-
/**
|
171 |
-
* Removes an attribute by name.
|
172 |
-
*
|
173 |
-
* @param string $name
|
174 |
-
*/
|
175 |
public function removeAttribute($name)
|
176 |
{
|
177 |
unset($this->attributes[$name]);
|
178 |
}
|
179 |
|
180 |
/**
|
181 |
-
* Returns true if the node with the given name exists.
|
182 |
-
*
|
183 |
-
* @param string $name
|
184 |
-
*
|
185 |
* @return bool
|
186 |
*/
|
187 |
public function hasNode($name)
|
@@ -190,10 +181,6 @@ class Twig_Node implements Twig_NodeInterface
|
|
190 |
}
|
191 |
|
192 |
/**
|
193 |
-
* Gets a node by name.
|
194 |
-
*
|
195 |
-
* @param string $name
|
196 |
-
*
|
197 |
* @return Twig_Node
|
198 |
*/
|
199 |
public function getNode($name)
|
@@ -205,22 +192,15 @@ class Twig_Node implements Twig_NodeInterface
|
|
205 |
return $this->nodes[$name];
|
206 |
}
|
207 |
|
208 |
-
/**
|
209 |
-
* Sets a node.
|
210 |
-
*
|
211 |
-
* @param string $name
|
212 |
-
* @param Twig_Node $node
|
213 |
-
*/
|
214 |
public function setNode($name, $node = null)
|
215 |
{
|
|
|
|
|
|
|
|
|
216 |
$this->nodes[$name] = $node;
|
217 |
}
|
218 |
|
219 |
-
/**
|
220 |
-
* Removes a node by name.
|
221 |
-
*
|
222 |
-
* @param string $name
|
223 |
-
*/
|
224 |
public function removeNode($name)
|
225 |
{
|
226 |
unset($this->nodes[$name]);
|
@@ -236,18 +216,38 @@ class Twig_Node implements Twig_NodeInterface
|
|
236 |
return new ArrayIterator($this->nodes);
|
237 |
}
|
238 |
|
239 |
-
public function
|
240 |
{
|
241 |
-
$this->
|
242 |
foreach ($this->nodes as $node) {
|
243 |
if (null !== $node) {
|
244 |
-
$node->
|
245 |
}
|
246 |
}
|
247 |
}
|
248 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
public function getFilename()
|
250 |
{
|
251 |
-
|
|
|
|
|
252 |
}
|
253 |
}
|
22 |
protected $lineno;
|
23 |
protected $tag;
|
24 |
|
25 |
+
private $name;
|
26 |
|
27 |
/**
|
28 |
* Constructor.
|
118 |
}
|
119 |
}
|
120 |
|
121 |
+
public function getTemplateLine()
|
122 |
+
{
|
123 |
+
return $this->lineno;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
128 |
+
*/
|
129 |
public function getLine()
|
130 |
{
|
131 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', E_USER_DEPRECATED);
|
132 |
+
|
133 |
return $this->lineno;
|
134 |
}
|
135 |
|
139 |
}
|
140 |
|
141 |
/**
|
142 |
+
* @return bool
|
|
|
|
|
|
|
|
|
143 |
*/
|
144 |
public function hasAttribute($name)
|
145 |
{
|
147 |
}
|
148 |
|
149 |
/**
|
|
|
|
|
|
|
|
|
150 |
* @return mixed
|
151 |
*/
|
152 |
public function getAttribute($name)
|
159 |
}
|
160 |
|
161 |
/**
|
|
|
|
|
162 |
* @param string $name
|
163 |
* @param mixed $value
|
164 |
*/
|
167 |
$this->attributes[$name] = $value;
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
|
|
170 |
public function removeAttribute($name)
|
171 |
{
|
172 |
unset($this->attributes[$name]);
|
173 |
}
|
174 |
|
175 |
/**
|
|
|
|
|
|
|
|
|
176 |
* @return bool
|
177 |
*/
|
178 |
public function hasNode($name)
|
181 |
}
|
182 |
|
183 |
/**
|
|
|
|
|
|
|
|
|
184 |
* @return Twig_Node
|
185 |
*/
|
186 |
public function getNode($name)
|
192 |
return $this->nodes[$name];
|
193 |
}
|
194 |
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
public function setNode($name, $node = null)
|
196 |
{
|
197 |
+
if (!$node instanceof Twig_NodeInterface) {
|
198 |
+
@trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED);
|
199 |
+
}
|
200 |
+
|
201 |
$this->nodes[$name] = $node;
|
202 |
}
|
203 |
|
|
|
|
|
|
|
|
|
|
|
204 |
public function removeNode($name)
|
205 |
{
|
206 |
unset($this->nodes[$name]);
|
216 |
return new ArrayIterator($this->nodes);
|
217 |
}
|
218 |
|
219 |
+
public function setTemplateName($name)
|
220 |
{
|
221 |
+
$this->name = $name;
|
222 |
foreach ($this->nodes as $node) {
|
223 |
if (null !== $node) {
|
224 |
+
$node->setTemplateName($name);
|
225 |
}
|
226 |
}
|
227 |
}
|
228 |
|
229 |
+
public function getTemplateName()
|
230 |
+
{
|
231 |
+
return $this->name;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
236 |
+
*/
|
237 |
+
public function setFilename($name)
|
238 |
+
{
|
239 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', E_USER_DEPRECATED);
|
240 |
+
|
241 |
+
$this->setTemplateName($name);
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
246 |
+
*/
|
247 |
public function getFilename()
|
248 |
{
|
249 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', E_USER_DEPRECATED);
|
250 |
+
|
251 |
+
return $this->name;
|
252 |
}
|
253 |
}
|
library/twig/twig/lib/Twig/Node/CheckSecurity.php
CHANGED
@@ -33,7 +33,7 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
33 |
foreach (array('tags', 'filters', 'functions') as $type) {
|
34 |
foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
|
35 |
if ($node instanceof Twig_Node) {
|
36 |
-
${$type}[$name] = $node->
|
37 |
} else {
|
38 |
${$type}[$node] = null;
|
39 |
}
|
@@ -46,7 +46,7 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
46 |
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
47 |
->write("try {\n")
|
48 |
->indent()
|
49 |
-
->write("\$this->env->getExtension('
|
50 |
->indent()
|
51 |
->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n")
|
52 |
->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n")
|
@@ -56,7 +56,7 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
56 |
->outdent()
|
57 |
->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
|
58 |
->indent()
|
59 |
-
->write("\$e->
|
60 |
->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
|
61 |
->indent()
|
62 |
->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
|
33 |
foreach (array('tags', 'filters', 'functions') as $type) {
|
34 |
foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
|
35 |
if ($node instanceof Twig_Node) {
|
36 |
+
${$type}[$name] = $node->getTemplateLine();
|
37 |
} else {
|
38 |
${$type}[$node] = null;
|
39 |
}
|
46 |
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
47 |
->write("try {\n")
|
48 |
->indent()
|
49 |
+
->write("\$this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity(\n")
|
50 |
->indent()
|
51 |
->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n")
|
52 |
->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n")
|
56 |
->outdent()
|
57 |
->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
|
58 |
->indent()
|
59 |
+
->write("\$e->setTemplateName(\$this->getTemplateName());\n\n")
|
60 |
->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
|
61 |
->indent()
|
62 |
->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
|
library/twig/twig/lib/Twig/Node/Embed.php
CHANGED
@@ -17,11 +17,13 @@
|
|
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($
|
21 |
{
|
22 |
parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
|
23 |
|
24 |
-
$this->setAttribute('
|
|
|
|
|
25 |
$this->setAttribute('index', $index);
|
26 |
}
|
27 |
|
@@ -29,11 +31,11 @@ class Twig_Node_Embed extends Twig_Node_Include
|
|
29 |
{
|
30 |
$compiler
|
31 |
->write('$this->loadTemplate(')
|
32 |
-
->string($this->getAttribute('
|
33 |
->raw(', ')
|
34 |
-
->repr($this->
|
35 |
->raw(', ')
|
36 |
-
->repr($this->
|
37 |
->raw(', ')
|
38 |
->string($this->getAttribute('index'))
|
39 |
->raw(')')
|
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($name, $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('name', $name);
|
25 |
+
// to be removed in 2.0, used name instead
|
26 |
+
$this->setAttribute('filename', $name);
|
27 |
$this->setAttribute('index', $index);
|
28 |
}
|
29 |
|
31 |
{
|
32 |
$compiler
|
33 |
->write('$this->loadTemplate(')
|
34 |
+
->string($this->getAttribute('name'))
|
35 |
->raw(', ')
|
36 |
+
->repr($this->getTemplateName())
|
37 |
->raw(', ')
|
38 |
+
->repr($this->getTemplateLine())
|
39 |
->raw(', ')
|
40 |
->string($this->getAttribute('index'))
|
41 |
->raw(')')
|
library/twig/twig/lib/Twig/Node/Expression/Array.php
CHANGED
@@ -43,7 +43,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
|
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
|
47 |
return true;
|
48 |
}
|
49 |
}
|
@@ -54,7 +54,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
|
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->
|
58 |
}
|
59 |
|
60 |
array_push($this->nodes, $key, $value);
|
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 |
}
|
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->getTemplateLine());
|
58 |
}
|
59 |
|
60 |
array_push($this->nodes, $key, $value);
|
library/twig/twig/lib/Twig/Node/Expression/Binary/Power.php
CHANGED
@@ -12,6 +12,10 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
|
|
12 |
{
|
13 |
public function compile(Twig_Compiler $compiler)
|
14 |
{
|
|
|
|
|
|
|
|
|
15 |
$compiler
|
16 |
->raw('pow(')
|
17 |
->subcompile($this->getNode('left'))
|
12 |
{
|
13 |
public function compile(Twig_Compiler $compiler)
|
14 |
{
|
15 |
+
if (PHP_VERSION_ID >= 50600) {
|
16 |
+
return parent::compile($compiler);
|
17 |
+
}
|
18 |
+
|
19 |
$compiler
|
20 |
->raw('pow(')
|
21 |
->subcompile($this->getNode('left'))
|
library/twig/twig/lib/Twig/Node/Expression/BlockReference.php
CHANGED
@@ -17,30 +17,75 @@
|
|
17 |
*/
|
18 |
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
19 |
{
|
20 |
-
|
|
|
|
|
|
|
21 |
{
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
}
|
24 |
|
25 |
public function compile(Twig_Compiler $compiler)
|
26 |
{
|
27 |
-
if ($this->getAttribute('
|
28 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
|
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
->subcompile($this->getNode('name'))
|
36 |
-
->raw(", \$context, \$blocks);\n")
|
37 |
-
;
|
38 |
} else {
|
39 |
$compiler
|
40 |
-
->
|
41 |
-
->subcompile($this->getNode('
|
42 |
-
->raw(',
|
|
|
|
|
|
|
|
|
43 |
;
|
44 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
}
|
46 |
}
|
17 |
*/
|
18 |
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @param Twig_Node|null $template
|
22 |
+
*/
|
23 |
+
public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
|
24 |
{
|
25 |
+
if (is_bool($template)) {
|
26 |
+
@trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
|
27 |
+
|
28 |
+
$template = null;
|
29 |
+
}
|
30 |
+
|
31 |
+
$nodes = array('name' => $name);
|
32 |
+
if (null !== $template) {
|
33 |
+
$nodes['template'] = $template;
|
34 |
+
}
|
35 |
+
|
36 |
+
parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag);
|
37 |
}
|
38 |
|
39 |
public function compile(Twig_Compiler $compiler)
|
40 |
{
|
41 |
+
if ($this->getAttribute('is_defined_test')) {
|
42 |
+
$this->compileTemplateCall($compiler, 'hasBlock');
|
43 |
+
} else {
|
44 |
+
if ($this->getAttribute('output')) {
|
45 |
+
$compiler->addDebugInfo($this);
|
46 |
+
|
47 |
+
$this
|
48 |
+
->compileTemplateCall($compiler, 'displayBlock')
|
49 |
+
->raw(";\n");
|
50 |
+
} else {
|
51 |
+
$this->compileTemplateCall($compiler, 'renderBlock');
|
52 |
+
}
|
53 |
}
|
54 |
+
}
|
55 |
|
56 |
+
private function compileTemplateCall(Twig_Compiler $compiler, $method)
|
57 |
+
{
|
58 |
+
if (!$this->hasNode('template')) {
|
59 |
+
$compiler->write('$this');
|
|
|
|
|
|
|
60 |
} else {
|
61 |
$compiler
|
62 |
+
->write('$this->loadTemplate(')
|
63 |
+
->subcompile($this->getNode('template'))
|
64 |
+
->raw(', ')
|
65 |
+
->repr($this->getTemplateName())
|
66 |
+
->raw(', ')
|
67 |
+
->repr($this->getTemplateLine())
|
68 |
+
->raw(')')
|
69 |
;
|
70 |
}
|
71 |
+
|
72 |
+
$compiler->raw(sprintf('->%s', $method));
|
73 |
+
$this->compileBlockArguments($compiler);
|
74 |
+
|
75 |
+
return $compiler;
|
76 |
+
}
|
77 |
+
|
78 |
+
private function compileBlockArguments(Twig_Compiler $compiler)
|
79 |
+
{
|
80 |
+
$compiler
|
81 |
+
->raw('(')
|
82 |
+
->subcompile($this->getNode('name'))
|
83 |
+
->raw(', $context');
|
84 |
+
|
85 |
+
if (!$this->hasNode('template')) {
|
86 |
+
$compiler->raw(', $blocks');
|
87 |
+
}
|
88 |
+
|
89 |
+
return $compiler->raw(')');
|
90 |
}
|
91 |
}
|
library/twig/twig/lib/Twig/Node/Expression/Call.php
CHANGED
@@ -10,18 +10,29 @@
|
|
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 |
-
$
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
} else {
|
27 |
$compiler->raw($this->getAttribute('thing')->compile());
|
@@ -121,7 +132,6 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
121 |
throw new LogicException($message);
|
122 |
}
|
123 |
|
124 |
-
// manage named arguments
|
125 |
$callableParameters = $this->getCallableParameters($callable, $isVariadic);
|
126 |
$arguments = array();
|
127 |
$names = array();
|
@@ -136,7 +146,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
136 |
throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
|
137 |
}
|
138 |
|
139 |
-
if (
|
140 |
throw new Twig_Error_Syntax(sprintf(
|
141 |
'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
|
142 |
$name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments))
|
@@ -195,7 +205,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
195 |
throw new Twig_Error_Syntax(sprintf(
|
196 |
'Unknown argument%s "%s" for %s "%s(%s)".',
|
197 |
count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
|
198 |
-
), $unknownParameter ? $unknownParameter->
|
199 |
}
|
200 |
|
201 |
return $arguments;
|
@@ -208,15 +218,9 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
208 |
|
209 |
private function getCallableParameters($callable, $isVariadic)
|
210 |
{
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
$r = new ReflectionObject($callable);
|
215 |
-
$r = $r->getMethod('__invoke');
|
216 |
-
} elseif (is_string($callable) && false !== strpos($callable, '::')) {
|
217 |
-
$r = new ReflectionMethod($callable);
|
218 |
-
} else {
|
219 |
-
$r = new ReflectionFunction($callable);
|
220 |
}
|
221 |
|
222 |
$parameters = $r->getParameters();
|
@@ -250,4 +254,36 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
250 |
|
251 |
return $parameters;
|
252 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
}
|
10 |
*/
|
11 |
abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
12 |
{
|
13 |
+
private $reflector;
|
14 |
+
|
15 |
protected function compileCallable(Twig_Compiler $compiler)
|
16 |
{
|
17 |
$closingParenthesis = false;
|
18 |
if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
|
19 |
+
if (is_string($callable) && false === strpos($callable, '::')) {
|
20 |
$compiler->raw($callable);
|
|
|
|
|
21 |
} else {
|
22 |
+
list($r, $callable) = $this->reflectCallable($callable);
|
23 |
+
if ($r instanceof ReflectionMethod && is_string($callable[0])) {
|
24 |
+
if ($r->isStatic()) {
|
25 |
+
$compiler->raw(sprintf('%s::%s', $callable[0], $callable[1]));
|
26 |
+
} else {
|
27 |
+
$compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1]));
|
28 |
+
}
|
29 |
+
} elseif ($r instanceof ReflectionMethod && $callable[0] instanceof Twig_ExtensionInterface) {
|
30 |
+
$compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', get_class($callable[0]), $callable[1]));
|
31 |
+
} else {
|
32 |
+
$type = ucfirst($this->getAttribute('type'));
|
33 |
+
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
|
34 |
+
$closingParenthesis = true;
|
35 |
+
}
|
36 |
}
|
37 |
} else {
|
38 |
$compiler->raw($this->getAttribute('thing')->compile());
|
132 |
throw new LogicException($message);
|
133 |
}
|
134 |
|
|
|
135 |
$callableParameters = $this->getCallableParameters($callable, $isVariadic);
|
136 |
$arguments = array();
|
137 |
$names = array();
|
146 |
throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
|
147 |
}
|
148 |
|
149 |
+
if (count($missingArguments)) {
|
150 |
throw new Twig_Error_Syntax(sprintf(
|
151 |
'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
|
152 |
$name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments))
|
205 |
throw new Twig_Error_Syntax(sprintf(
|
206 |
'Unknown argument%s "%s" for %s "%s(%s)".',
|
207 |
count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
|
208 |
+
), $unknownParameter ? $unknownParameter->getTemplateLine() : -1);
|
209 |
}
|
210 |
|
211 |
return $arguments;
|
218 |
|
219 |
private function getCallableParameters($callable, $isVariadic)
|
220 |
{
|
221 |
+
list($r) = $this->reflectCallable($callable);
|
222 |
+
if (null === $r) {
|
223 |
+
return array();
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
}
|
225 |
|
226 |
$parameters = $r->getParameters();
|
254 |
|
255 |
return $parameters;
|
256 |
}
|
257 |
+
|
258 |
+
private function reflectCallable($callable)
|
259 |
+
{
|
260 |
+
if (null !== $this->reflector) {
|
261 |
+
return $this->reflector;
|
262 |
+
}
|
263 |
+
|
264 |
+
if (is_array($callable)) {
|
265 |
+
if (!method_exists($callable[0], $callable[1])) {
|
266 |
+
// __call()
|
267 |
+
return array(null, array());
|
268 |
+
}
|
269 |
+
$r = new ReflectionMethod($callable[0], $callable[1]);
|
270 |
+
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
271 |
+
$r = new ReflectionObject($callable);
|
272 |
+
$r = $r->getMethod('__invoke');
|
273 |
+
$callable = array($callable, '__invoke');
|
274 |
+
} elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
275 |
+
$class = substr($callable, 0, $pos);
|
276 |
+
$method = substr($callable, $pos + 2);
|
277 |
+
if (!method_exists($class, $method)) {
|
278 |
+
// __staticCall()
|
279 |
+
return array(null, array());
|
280 |
+
}
|
281 |
+
$r = new ReflectionMethod($callable);
|
282 |
+
$callable = array($class, $method);
|
283 |
+
} else {
|
284 |
+
$r = new ReflectionFunction($callable);
|
285 |
+
}
|
286 |
+
|
287 |
+
return $this->reflector = array($r, $callable);
|
288 |
+
}
|
289 |
}
|
library/twig/twig/lib/Twig/Node/Expression/Filter/Default.php
CHANGED
@@ -22,13 +22,13 @@ 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->
|
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->
|
29 |
-
$false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->
|
30 |
|
31 |
-
$node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->
|
32 |
} else {
|
33 |
$node = $default;
|
34 |
}
|
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->getTemplateLine()), $arguments, $node->getTemplateLine());
|
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->getTemplateLine());
|
29 |
+
$false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine());
|
30 |
|
31 |
+
$node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine());
|
32 |
} else {
|
33 |
$node = $default;
|
34 |
}
|
library/twig/twig/lib/Twig/Node/Expression/Function.php
CHANGED
@@ -12,7 +12,7 @@ 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)
|
@@ -27,7 +27,12 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
|
27 |
$this->setAttribute('needs_context', $function->needsContext());
|
28 |
$this->setAttribute('arguments', $function->getArguments());
|
29 |
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
30 |
-
$
|
|
|
|
|
|
|
|
|
|
|
31 |
}
|
32 |
if ($function instanceof Twig_SimpleFunction) {
|
33 |
$this->setAttribute('is_variadic', $function->isVariadic());
|
12 |
{
|
13 |
public function __construct($name, Twig_NodeInterface $arguments, $lineno)
|
14 |
{
|
15 |
+
parent::__construct(array('arguments' => $arguments), array('name' => $name, 'is_defined_test' => false), $lineno);
|
16 |
}
|
17 |
|
18 |
public function compile(Twig_Compiler $compiler)
|
27 |
$this->setAttribute('needs_context', $function->needsContext());
|
28 |
$this->setAttribute('arguments', $function->getArguments());
|
29 |
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
30 |
+
$callable = $function->getCallable();
|
31 |
+
if ('constant' === $name && $this->getAttribute('is_defined_test')) {
|
32 |
+
$callable = 'twig_constant_is_defined';
|
33 |
+
}
|
34 |
+
|
35 |
+
$this->setAttribute('callable', $callable);
|
36 |
}
|
37 |
if ($function instanceof Twig_SimpleFunction) {
|
38 |
$this->setAttribute('is_variadic', $function->isVariadic());
|
library/twig/twig/lib/Twig/Node/Expression/Name.php
CHANGED
@@ -43,10 +43,20 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|
43 |
->raw(']')
|
44 |
;
|
45 |
} else {
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
// PHP 5.4 ternary operator performance was optimized
|
51 |
$compiler
|
52 |
->raw('(isset($context[')
|
43 |
->raw(']')
|
44 |
;
|
45 |
} else {
|
46 |
+
if (PHP_VERSION_ID >= 70000) {
|
47 |
+
// use PHP 7 null coalescing operator
|
48 |
+
$compiler
|
49 |
+
->raw('($context[')
|
50 |
+
->string($name)
|
51 |
+
->raw('] ?? ')
|
52 |
+
;
|
53 |
+
|
54 |
+
if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
|
55 |
+
$compiler->raw('null)');
|
56 |
+
} else {
|
57 |
+
$compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
|
58 |
+
}
|
59 |
+
} elseif (PHP_VERSION_ID >= 50400) {
|
60 |
// PHP 5.4 ternary operator performance was optimized
|
61 |
$compiler
|
62 |
->raw('(isset($context[')
|
library/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php
CHANGED
@@ -13,11 +13,34 @@ class Twig_Node_Expression_NullCoalesce extends Twig_Node_Expression_Conditional
|
|
13 |
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
14 |
{
|
15 |
$test = new Twig_Node_Expression_Binary_And(
|
16 |
-
new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->
|
17 |
-
new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->
|
18 |
-
$left->
|
19 |
);
|
20 |
|
21 |
parent::__construct($test, $left, $right, $lineno);
|
22 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
}
|
13 |
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
14 |
{
|
15 |
$test = new Twig_Node_Expression_Binary_And(
|
16 |
+
new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getTemplateLine()),
|
17 |
+
new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getTemplateLine()), $left->getTemplateLine()),
|
18 |
+
$left->getTemplateLine()
|
19 |
);
|
20 |
|
21 |
parent::__construct($test, $left, $right, $lineno);
|
22 |
}
|
23 |
+
|
24 |
+
public function compile(Twig_Compiler $compiler)
|
25 |
+
{
|
26 |
+
/*
|
27 |
+
* This optimizes only one case. PHP 7 also supports more complex expressions
|
28 |
+
* that can return null. So, for instance, if log is defined, log("foo") ?? "..." works,
|
29 |
+
* but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced
|
30 |
+
* cases might be implemented as an optimizer node visitor, but has not been done
|
31 |
+
* as benefits are probably not worth the added complexity.
|
32 |
+
*/
|
33 |
+
if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof Twig_Node_Expression_Name) {
|
34 |
+
$this->getNode('expr2')->setAttribute('always_defined', true);
|
35 |
+
$compiler
|
36 |
+
->raw('((')
|
37 |
+
->subcompile($this->getNode('expr2'))
|
38 |
+
->raw(') ?? (')
|
39 |
+
->subcompile($this->getNode('expr3'))
|
40 |
+
->raw('))')
|
41 |
+
;
|
42 |
+
} else {
|
43 |
+
parent::compile($compiler);
|
44 |
+
}
|
45 |
+
}
|
46 |
}
|
library/twig/twig/lib/Twig/Node/Expression/Test/Defined.php
CHANGED
@@ -29,12 +29,15 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
|
29 |
$node->setAttribute('is_defined_test', true);
|
30 |
} elseif ($node instanceof Twig_Node_Expression_GetAttr) {
|
31 |
$node->setAttribute('is_defined_test', true);
|
32 |
-
|
33 |
$this->changeIgnoreStrictCheck($node);
|
|
|
|
|
|
|
|
|
34 |
} elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) {
|
35 |
-
$node = new Twig_Node_Expression_Constant(true, $node->
|
36 |
} else {
|
37 |
-
throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->
|
38 |
}
|
39 |
|
40 |
parent::__construct($node, $name, $arguments, $lineno);
|
29 |
$node->setAttribute('is_defined_test', true);
|
30 |
} elseif ($node instanceof Twig_Node_Expression_GetAttr) {
|
31 |
$node->setAttribute('is_defined_test', true);
|
|
|
32 |
$this->changeIgnoreStrictCheck($node);
|
33 |
+
} elseif ($node instanceof Twig_Node_Expression_BlockReference) {
|
34 |
+
$node->setAttribute('is_defined_test', true);
|
35 |
+
} elseif ($node instanceof Twig_Node_Expression_Function && 'constant' === $node->getAttribute('name')) {
|
36 |
+
$node->setAttribute('is_defined_test', true);
|
37 |
} elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) {
|
38 |
+
$node = new Twig_Node_Expression_Constant(true, $node->getTemplateLine());
|
39 |
} else {
|
40 |
+
throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getTemplateLine());
|
41 |
}
|
42 |
|
43 |
parent::__construct($node, $name, $arguments, $lineno);
|
library/twig/twig/lib/Twig/Node/Import.php
CHANGED
@@ -37,9 +37,9 @@ class Twig_Node_Import extends Twig_Node
|
|
37 |
->raw('$this->loadTemplate(')
|
38 |
->subcompile($this->getNode('expr'))
|
39 |
->raw(', ')
|
40 |
-
->repr($this->
|
41 |
->raw(', ')
|
42 |
-
->repr($this->
|
43 |
->raw(')')
|
44 |
;
|
45 |
}
|
37 |
->raw('$this->loadTemplate(')
|
38 |
->subcompile($this->getNode('expr'))
|
39 |
->raw(', ')
|
40 |
+
->repr($this->getTemplateName())
|
41 |
->raw(', ')
|
42 |
+
->repr($this->getTemplateLine())
|
43 |
->raw(')')
|
44 |
;
|
45 |
}
|
library/twig/twig/lib/Twig/Node/Include.php
CHANGED
@@ -64,9 +64,9 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|
64 |
->write('$this->loadTemplate(')
|
65 |
->subcompile($this->getNode('expr'))
|
66 |
->raw(', ')
|
67 |
-
->repr($this->
|
68 |
->raw(', ')
|
69 |
-
->repr($this->
|
70 |
->raw(')')
|
71 |
;
|
72 |
}
|
64 |
->write('$this->loadTemplate(')
|
65 |
->subcompile($this->getNode('expr'))
|
66 |
->raw(', ')
|
67 |
+
->repr($this->getTemplateName())
|
68 |
->raw(', ')
|
69 |
+
->repr($this->getTemplateLine())
|
70 |
->raw(')')
|
71 |
;
|
72 |
}
|
library/twig/twig/lib/Twig/Node/Macro.php
CHANGED
@@ -22,7 +22,7 @@ class Twig_Node_Macro extends Twig_Node
|
|
22 |
{
|
23 |
foreach ($arguments as $argumentName => $argument) {
|
24 |
if (self::VARARGS_NAME === $argumentName) {
|
25 |
-
throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->
|
26 |
}
|
27 |
}
|
28 |
|
@@ -70,7 +70,7 @@ class Twig_Node_Macro extends Twig_Node
|
|
70 |
|
71 |
foreach ($this->getNode('arguments') as $name => $default) {
|
72 |
$compiler
|
73 |
-
->
|
74 |
->string($name)
|
75 |
->raw(' => $__'.$name.'__')
|
76 |
->raw(",\n")
|
@@ -78,7 +78,7 @@ class Twig_Node_Macro extends Twig_Node
|
|
78 |
}
|
79 |
|
80 |
$compiler
|
81 |
-
->
|
82 |
->string(self::VARARGS_NAME)
|
83 |
->raw(' => ')
|
84 |
;
|
22 |
{
|
23 |
foreach ($arguments as $argumentName => $argument) {
|
24 |
if (self::VARARGS_NAME === $argumentName) {
|
25 |
+
throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine());
|
26 |
}
|
27 |
}
|
28 |
|
70 |
|
71 |
foreach ($this->getNode('arguments') as $name => $default) {
|
72 |
$compiler
|
73 |
+
->write('')
|
74 |
->string($name)
|
75 |
->raw(' => $__'.$name.'__')
|
76 |
->raw(",\n")
|
78 |
}
|
79 |
|
80 |
$compiler
|
81 |
+
->write('')
|
82 |
->string(self::VARARGS_NAME)
|
83 |
->raw(' => ')
|
84 |
;
|
library/twig/twig/lib/Twig/Node/Module.php
CHANGED
@@ -21,8 +21,17 @@
|
|
21 |
*/
|
22 |
class Twig_Node_Module extends Twig_Node
|
23 |
{
|
24 |
-
|
|
|
|
|
25 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
$nodes = array(
|
27 |
'body' => $body,
|
28 |
'blocks' => $blocks,
|
@@ -40,11 +49,16 @@ class Twig_Node_Module extends Twig_Node
|
|
40 |
|
41 |
// embedded templates are set as attributes so that they are only visited once by the visitors
|
42 |
parent::__construct($nodes, array(
|
43 |
-
|
44 |
-
'
|
|
|
|
|
45 |
'index' => null,
|
46 |
'embedded_templates' => $embeddedTemplates,
|
47 |
), 1);
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
public function setIndex($index)
|
@@ -96,6 +110,8 @@ class Twig_Node_Module extends Twig_Node
|
|
96 |
|
97 |
$this->compileGetSource($compiler);
|
98 |
|
|
|
|
|
99 |
$this->compileClassFooter($compiler);
|
100 |
}
|
101 |
|
@@ -120,9 +136,9 @@ class Twig_Node_Module extends Twig_Node
|
|
120 |
->raw('$this->loadTemplate(')
|
121 |
->subcompile($parent)
|
122 |
->raw(', ')
|
123 |
-
->repr($this->
|
124 |
->raw(', ')
|
125 |
-
->repr($parent->
|
126 |
->raw(')')
|
127 |
;
|
128 |
}
|
@@ -138,9 +154,9 @@ class Twig_Node_Module extends Twig_Node
|
|
138 |
{
|
139 |
$compiler
|
140 |
->write("\n\n")
|
141 |
-
// if the
|
142 |
-
->write('/* '.str_replace('*/', '* /', $this->
|
143 |
-
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->
|
144 |
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
|
145 |
->write("{\n")
|
146 |
->indent()
|
@@ -165,9 +181,9 @@ class Twig_Node_Module extends Twig_Node
|
|
165 |
->write('$this->parent = $this->loadTemplate(')
|
166 |
->subcompile($parent)
|
167 |
->raw(', ')
|
168 |
-
->repr($this->
|
169 |
->raw(', ')
|
170 |
-
->repr($parent->
|
171 |
->raw(");\n")
|
172 |
;
|
173 |
}
|
@@ -323,7 +339,7 @@ class Twig_Node_Module extends Twig_Node
|
|
323 |
->write("public function getTemplateName()\n", "{\n")
|
324 |
->indent()
|
325 |
->write('return ')
|
326 |
-
->repr($this->
|
327 |
->raw(";\n")
|
328 |
->outdent()
|
329 |
->write("}\n\n")
|
@@ -396,11 +412,29 @@ class Twig_Node_Module extends Twig_Node
|
|
396 |
protected function compileGetSource(Twig_Compiler $compiler)
|
397 |
{
|
398 |
$compiler
|
|
|
399 |
->write("public function getSource()\n", "{\n")
|
400 |
->indent()
|
401 |
-
->write('
|
402 |
-
->
|
403 |
-
->raw("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
->outdent()
|
405 |
->write("}\n")
|
406 |
;
|
@@ -413,13 +447,13 @@ class Twig_Node_Module extends Twig_Node
|
|
413 |
->write(sprintf('%s = $this->loadTemplate(', $var))
|
414 |
->subcompile($node)
|
415 |
->raw(', ')
|
416 |
-
->repr($
|
417 |
->raw(', ')
|
418 |
-
->repr($node->
|
419 |
->raw(");\n")
|
420 |
;
|
421 |
} else {
|
422 |
-
throw new LogicException('Trait templates can only be constant nodes');
|
423 |
}
|
424 |
}
|
425 |
}
|
21 |
*/
|
22 |
class Twig_Node_Module extends Twig_Node
|
23 |
{
|
24 |
+
private $source;
|
25 |
+
|
26 |
+
public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '')
|
27 |
{
|
28 |
+
if (!$name instanceof Twig_Source) {
|
29 |
+
@trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
|
30 |
+
$this->source = new Twig_Source($source, $name);
|
31 |
+
} else {
|
32 |
+
$this->source = $name;
|
33 |
+
}
|
34 |
+
|
35 |
$nodes = array(
|
36 |
'body' => $body,
|
37 |
'blocks' => $blocks,
|
49 |
|
50 |
// embedded templates are set as attributes so that they are only visited once by the visitors
|
51 |
parent::__construct($nodes, array(
|
52 |
+
// source to be remove in 2.0
|
53 |
+
'source' => $this->source->getCode(),
|
54 |
+
// filename to be remove in 2.0 (use getTemplateName() instead)
|
55 |
+
'filename' => $this->source->getName(),
|
56 |
'index' => null,
|
57 |
'embedded_templates' => $embeddedTemplates,
|
58 |
), 1);
|
59 |
+
|
60 |
+
// populate the template name of all node children
|
61 |
+
$this->setTemplateName($this->source->getName());
|
62 |
}
|
63 |
|
64 |
public function setIndex($index)
|
110 |
|
111 |
$this->compileGetSource($compiler);
|
112 |
|
113 |
+
$this->compileGetSourceContext($compiler);
|
114 |
+
|
115 |
$this->compileClassFooter($compiler);
|
116 |
}
|
117 |
|
136 |
->raw('$this->loadTemplate(')
|
137 |
->subcompile($parent)
|
138 |
->raw(', ')
|
139 |
+
->repr($this->source->getName())
|
140 |
->raw(', ')
|
141 |
+
->repr($parent->getTemplateLine())
|
142 |
->raw(')')
|
143 |
;
|
144 |
}
|
154 |
{
|
155 |
$compiler
|
156 |
->write("\n\n")
|
157 |
+
// if the template name contains */, add a blank to avoid a PHP parse error
|
158 |
+
->write('/* '.str_replace('*/', '* /', $this->source->getName())." */\n")
|
159 |
+
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->source->getName(), $this->getAttribute('index')))
|
160 |
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
|
161 |
->write("{\n")
|
162 |
->indent()
|
181 |
->write('$this->parent = $this->loadTemplate(')
|
182 |
->subcompile($parent)
|
183 |
->raw(', ')
|
184 |
+
->repr($this->source->getName())
|
185 |
->raw(', ')
|
186 |
+
->repr($parent->getTemplateLine())
|
187 |
->raw(");\n")
|
188 |
;
|
189 |
}
|
339 |
->write("public function getTemplateName()\n", "{\n")
|
340 |
->indent()
|
341 |
->write('return ')
|
342 |
+
->repr($this->source->getName())
|
343 |
->raw(";\n")
|
344 |
->outdent()
|
345 |
->write("}\n\n")
|
412 |
protected function compileGetSource(Twig_Compiler $compiler)
|
413 |
{
|
414 |
$compiler
|
415 |
+
->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n")
|
416 |
->write("public function getSource()\n", "{\n")
|
417 |
->indent()
|
418 |
+
->write("@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);\n\n")
|
419 |
+
->write('return $this->getSourceContext()->getCode();')
|
420 |
+
->raw("\n")
|
421 |
+
->outdent()
|
422 |
+
->write("}\n\n")
|
423 |
+
;
|
424 |
+
}
|
425 |
+
|
426 |
+
protected function compileGetSourceContext(Twig_Compiler $compiler)
|
427 |
+
{
|
428 |
+
$compiler
|
429 |
+
->write("public function getSourceContext()\n", "{\n")
|
430 |
+
->indent()
|
431 |
+
->write('return new Twig_Source(')
|
432 |
+
->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '')
|
433 |
+
->raw(', ')
|
434 |
+
->string($this->source->getName())
|
435 |
+
->raw(', ')
|
436 |
+
->string($this->source->getPath())
|
437 |
+
->raw(");\n")
|
438 |
->outdent()
|
439 |
->write("}\n")
|
440 |
;
|
447 |
->write(sprintf('%s = $this->loadTemplate(', $var))
|
448 |
->subcompile($node)
|
449 |
->raw(', ')
|
450 |
+
->repr($node->getTemplateName())
|
451 |
->raw(', ')
|
452 |
+
->repr($node->getTemplateLine())
|
453 |
->raw(");\n")
|
454 |
;
|
455 |
} else {
|
456 |
+
throw new LogicException('Trait templates can only be constant nodes.');
|
457 |
}
|
458 |
}
|
459 |
}
|
library/twig/twig/lib/Twig/Node/Sandbox.php
CHANGED
@@ -25,7 +25,7 @@ class Twig_Node_Sandbox extends Twig_Node
|
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
28 |
-
->write("\$sandbox = \$this->env->getExtension('
|
29 |
->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
|
30 |
->indent()
|
31 |
->write("\$sandbox->enableSandbox();\n")
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
28 |
+
->write("\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');\n")
|
29 |
->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
|
30 |
->indent()
|
31 |
->write("\$sandbox->enableSandbox();\n")
|
library/twig/twig/lib/Twig/Node/SandboxedPrint.php
CHANGED
@@ -25,7 +25,7 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
28 |
-
->write('echo $this->env->getExtension(\'
|
29 |
->subcompile($this->getNode('expr'))
|
30 |
->raw(");\n")
|
31 |
;
|
@@ -36,11 +36,9 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
|
36 |
*
|
37 |
* This is mostly needed when another visitor adds filters (like the escaper one).
|
38 |
*
|
39 |
-
* @param Twig_Node $node A Node
|
40 |
-
*
|
41 |
* @return Twig_Node
|
42 |
*/
|
43 |
-
protected function removeNodeFilter($node)
|
44 |
{
|
45 |
if ($node instanceof Twig_Node_Expression_Filter) {
|
46 |
return $this->removeNodeFilter($node->getNode('node'));
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
28 |
+
->write('echo $this->env->getExtension(\'Twig_Extension_Sandbox\')->ensureToStringAllowed(')
|
29 |
->subcompile($this->getNode('expr'))
|
30 |
->raw(");\n")
|
31 |
;
|
36 |
*
|
37 |
* This is mostly needed when another visitor adds filters (like the escaper one).
|
38 |
*
|
|
|
|
|
39 |
* @return Twig_Node
|
40 |
*/
|
41 |
+
protected function removeNodeFilter(Twig_Node $node)
|
42 |
{
|
43 |
if ($node instanceof Twig_Node_Expression_Filter) {
|
44 |
return $this->removeNodeFilter($node->getNode('node'));
|
library/twig/twig/lib/Twig/Node/Set.php
CHANGED
@@ -30,7 +30,7 @@ class Twig_Node_Set extends Twig_Node
|
|
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->
|
34 |
$this->setAttribute('capture', false);
|
35 |
}
|
36 |
}
|
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->getTemplateLine()));
|
34 |
$this->setAttribute('capture', false);
|
35 |
}
|
36 |
}
|
library/twig/twig/lib/Twig/Node/With.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 2016 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 nested "with" scope.
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*/
|
17 |
+
class Twig_Node_With extends Twig_Node
|
18 |
+
{
|
19 |
+
public function __construct(Twig_Node $body, Twig_Node $variables = null, $only = false, $lineno, $tag = null)
|
20 |
+
{
|
21 |
+
$nodes = array('body' => $body);
|
22 |
+
if (null !== $variables) {
|
23 |
+
$nodes['variables'] = $variables;
|
24 |
+
}
|
25 |
+
|
26 |
+
parent::__construct($nodes, array('only' => (bool) $only), $lineno, $tag);
|
27 |
+
}
|
28 |
+
|
29 |
+
public function compile(Twig_Compiler $compiler)
|
30 |
+
{
|
31 |
+
$compiler->addDebugInfo($this);
|
32 |
+
|
33 |
+
if ($this->hasNode('variables')) {
|
34 |
+
$varsName = $compiler->getVarName();
|
35 |
+
$compiler
|
36 |
+
->write(sprintf('$%s = ', $varsName))
|
37 |
+
->subcompile($this->getNode('variables'))
|
38 |
+
->raw(";\n")
|
39 |
+
->write(sprintf("if (!is_array(\$%s)) {\n", $varsName))
|
40 |
+
->indent()
|
41 |
+
->write("throw new Twig_Error_Runtime('Variables passed to the \"with\" tag must be a hash.');\n")
|
42 |
+
->outdent()
|
43 |
+
->write("}\n")
|
44 |
+
;
|
45 |
+
|
46 |
+
if ($this->getAttribute('only')) {
|
47 |
+
$compiler->write("\$context = array('_parent' => \$context);\n");
|
48 |
+
} else {
|
49 |
+
$compiler->write("\$context['_parent'] = \$context;\n");
|
50 |
+
}
|
51 |
+
|
52 |
+
$compiler->write(sprintf("\$context = array_merge(\$context, \$%s);\n", $varsName));
|
53 |
+
} else {
|
54 |
+
$compiler->write("\$context['_parent'] = \$context;\n");
|
55 |
+
}
|
56 |
+
|
57 |
+
$compiler
|
58 |
+
->subcompile($this->getNode('body'))
|
59 |
+
->write("\$context = \$context['_parent'];\n")
|
60 |
+
;
|
61 |
+
}
|
62 |
+
}
|
library/twig/twig/lib/Twig/NodeInterface.php
CHANGED
@@ -20,11 +20,12 @@ interface Twig_NodeInterface extends Countable, IteratorAggregate
|
|
20 |
{
|
21 |
/**
|
22 |
* Compiles the node to PHP.
|
23 |
-
*
|
24 |
-
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
25 |
*/
|
26 |
public function compile(Twig_Compiler $compiler);
|
27 |
|
|
|
|
|
|
|
28 |
public function getLine();
|
29 |
|
30 |
public function getNodeTag();
|
20 |
{
|
21 |
/**
|
22 |
* Compiles the node to PHP.
|
|
|
|
|
23 |
*/
|
24 |
public function compile(Twig_Compiler $compiler);
|
25 |
|
26 |
+
/**
|
27 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
28 |
+
*/
|
29 |
public function getLine();
|
30 |
|
31 |
public function getNodeTag();
|
library/twig/twig/lib/Twig/NodeTraverser.php
CHANGED
@@ -22,10 +22,8 @@ class Twig_NodeTraverser
|
|
22 |
protected $visitors = array();
|
23 |
|
24 |
/**
|
25 |
-
*
|
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 |
{
|
@@ -35,11 +33,6 @@ class Twig_NodeTraverser
|
|
35 |
}
|
36 |
}
|
37 |
|
38 |
-
/**
|
39 |
-
* Adds a visitor.
|
40 |
-
*
|
41 |
-
* @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
|
42 |
-
*/
|
43 |
public function addVisitor(Twig_NodeVisitorInterface $visitor)
|
44 |
{
|
45 |
if (!isset($this->visitors[$visitor->getPriority()])) {
|
@@ -52,8 +45,6 @@ class Twig_NodeTraverser
|
|
52 |
/**
|
53 |
* Traverses a node and calls the registered visitors.
|
54 |
*
|
55 |
-
* @param Twig_NodeInterface $node A Twig_NodeInterface instance
|
56 |
-
*
|
57 |
* @return Twig_NodeInterface
|
58 |
*/
|
59 |
public function traverse(Twig_NodeInterface $node)
|
22 |
protected $visitors = array();
|
23 |
|
24 |
/**
|
25 |
+
* @param Twig_Environment $env
|
26 |
+
* @param Twig_NodeVisitorInterface[] $visitors
|
|
|
|
|
27 |
*/
|
28 |
public function __construct(Twig_Environment $env, array $visitors = array())
|
29 |
{
|
33 |
}
|
34 |
}
|
35 |
|
|
|
|
|
|
|
|
|
|
|
36 |
public function addVisitor(Twig_NodeVisitorInterface $visitor)
|
37 |
{
|
38 |
if (!isset($this->visitors[$visitor->getPriority()])) {
|
45 |
/**
|
46 |
* Traverses a node and calls the registered visitors.
|
47 |
*
|
|
|
|
|
48 |
* @return Twig_NodeInterface
|
49 |
*/
|
50 |
public function traverse(Twig_NodeInterface $node)
|
library/twig/twig/lib/Twig/NodeVisitor/Escaper.php
CHANGED
@@ -34,7 +34,7 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
34 |
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
35 |
{
|
36 |
if ($node instanceof Twig_Node_Module) {
|
37 |
-
if ($env->hasExtension('
|
38 |
$this->defaultStrategy = $defaultStrategy;
|
39 |
}
|
40 |
$this->safeVars = array();
|
@@ -90,7 +90,7 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
90 |
|
91 |
return new $class(
|
92 |
$this->getEscaperFilter($type, $expression),
|
93 |
-
$node->
|
94 |
);
|
95 |
}
|
96 |
|
@@ -142,7 +142,7 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
142 |
|
143 |
protected function getEscaperFilter($type, Twig_NodeInterface $node)
|
144 |
{
|
145 |
-
$line = $node->
|
146 |
$name = new Twig_Node_Expression_Constant('escape', $line);
|
147 |
$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)));
|
148 |
|
34 |
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
35 |
{
|
36 |
if ($node instanceof Twig_Node_Module) {
|
37 |
+
if ($env->hasExtension('Twig_Extension_Escaper') && $defaultStrategy = $env->getExtension('Twig_Extension_Escaper')->getDefaultStrategy($node->getTemplateName())) {
|
38 |
$this->defaultStrategy = $defaultStrategy;
|
39 |
}
|
40 |
$this->safeVars = array();
|
90 |
|
91 |
return new $class(
|
92 |
$this->getEscaperFilter($type, $expression),
|
93 |
+
$node->getTemplateLine()
|
94 |
);
|
95 |
}
|
96 |
|
142 |
|
143 |
protected function getEscaperFilter($type, Twig_NodeInterface $node)
|
144 |
{
|
145 |
+
$line = $node->getTemplateLine();
|
146 |
$name = new Twig_Node_Expression_Constant('escape', $line);
|
147 |
$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)));
|
148 |
|
library/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
CHANGED
@@ -34,8 +34,6 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
34 |
protected $inABody = false;
|
35 |
|
36 |
/**
|
37 |
-
* Constructor.
|
38 |
-
*
|
39 |
* @param int $optimizers The optimizer mode
|
40 |
*/
|
41 |
public function __construct($optimizers = -1)
|
@@ -56,7 +54,7 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
56 |
$this->enterOptimizeFor($node, $env);
|
57 |
}
|
58 |
|
59 |
-
if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('
|
60 |
if ($this->inABody) {
|
61 |
if (!$node instanceof Twig_Node_Expression) {
|
62 |
if (get_class($node) !== 'Twig_Node') {
|
@@ -90,14 +88,14 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
90 |
|
91 |
$node = $this->optimizePrintNode($node, $env);
|
92 |
|
93 |
-
if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('
|
94 |
if ($node instanceof Twig_Node_Body) {
|
95 |
$this->inABody = false;
|
96 |
} elseif ($this->inABody) {
|
97 |
if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
|
98 |
$nodes = array();
|
99 |
foreach (array_unique($prependedNodes) as $name) {
|
100 |
-
$nodes[] = new Twig_Node_SetTemp($name, $node->
|
101 |
}
|
102 |
|
103 |
$nodes[] = $node;
|
@@ -114,7 +112,7 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
114 |
if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
|
115 |
$this->prependedNodes[0][] = $node->getAttribute('name');
|
116 |
|
117 |
-
return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->
|
118 |
}
|
119 |
|
120 |
return $node;
|
@@ -127,9 +125,6 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
127 |
*
|
128 |
* * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
|
129 |
*
|
130 |
-
* @param Twig_NodeInterface $node A Node
|
131 |
-
* @param Twig_Environment $env The current Twig environment
|
132 |
-
*
|
133 |
* @return Twig_NodeInterface
|
134 |
*/
|
135 |
protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
|
@@ -138,13 +133,14 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
138 |
return $node;
|
139 |
}
|
140 |
|
|
|
141 |
if (
|
142 |
-
$
|
143 |
-
$
|
144 |
) {
|
145 |
-
$
|
146 |
|
147 |
-
return $
|
148 |
}
|
149 |
|
150 |
return $node;
|
@@ -153,9 +149,6 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
153 |
/**
|
154 |
* Removes "raw" filters.
|
155 |
*
|
156 |
-
* @param Twig_NodeInterface $node A Node
|
157 |
-
* @param Twig_Environment $env The current Twig environment
|
158 |
-
*
|
159 |
* @return Twig_NodeInterface
|
160 |
*/
|
161 |
protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
|
@@ -169,9 +162,6 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
169 |
|
170 |
/**
|
171 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
172 |
-
*
|
173 |
-
* @param Twig_NodeInterface $node A Node
|
174 |
-
* @param Twig_Environment $env The current Twig environment
|
175 |
*/
|
176 |
protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
|
177 |
{
|
@@ -236,9 +226,6 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
236 |
|
237 |
/**
|
238 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
239 |
-
*
|
240 |
-
* @param Twig_NodeInterface $node A Node
|
241 |
-
* @param Twig_Environment $env The current Twig environment
|
242 |
*/
|
243 |
protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
|
244 |
{
|
34 |
protected $inABody = false;
|
35 |
|
36 |
/**
|
|
|
|
|
37 |
* @param int $optimizers The optimizer mode
|
38 |
*/
|
39 |
public function __construct($optimizers = -1)
|
54 |
$this->enterOptimizeFor($node, $env);
|
55 |
}
|
56 |
|
57 |
+
if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) {
|
58 |
if ($this->inABody) {
|
59 |
if (!$node instanceof Twig_Node_Expression) {
|
60 |
if (get_class($node) !== 'Twig_Node') {
|
88 |
|
89 |
$node = $this->optimizePrintNode($node, $env);
|
90 |
|
91 |
+
if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) {
|
92 |
if ($node instanceof Twig_Node_Body) {
|
93 |
$this->inABody = false;
|
94 |
} elseif ($this->inABody) {
|
95 |
if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
|
96 |
$nodes = array();
|
97 |
foreach (array_unique($prependedNodes) as $name) {
|
98 |
+
$nodes[] = new Twig_Node_SetTemp($name, $node->getTemplateLine());
|
99 |
}
|
100 |
|
101 |
$nodes[] = $node;
|
112 |
if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
|
113 |
$this->prependedNodes[0][] = $node->getAttribute('name');
|
114 |
|
115 |
+
return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getTemplateLine());
|
116 |
}
|
117 |
|
118 |
return $node;
|
125 |
*
|
126 |
* * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
|
127 |
*
|
|
|
|
|
|
|
128 |
* @return Twig_NodeInterface
|
129 |
*/
|
130 |
protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
|
133 |
return $node;
|
134 |
}
|
135 |
|
136 |
+
$exprNode = $node->getNode('expr');
|
137 |
if (
|
138 |
+
$exprNode instanceof Twig_Node_Expression_BlockReference ||
|
139 |
+
$exprNode instanceof Twig_Node_Expression_Parent
|
140 |
) {
|
141 |
+
$exprNode->setAttribute('output', true);
|
142 |
|
143 |
+
return $exprNode;
|
144 |
}
|
145 |
|
146 |
return $node;
|
149 |
/**
|
150 |
* Removes "raw" filters.
|
151 |
*
|
|
|
|
|
|
|
152 |
* @return Twig_NodeInterface
|
153 |
*/
|
154 |
protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
|
162 |
|
163 |
/**
|
164 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
|
|
|
|
|
|
165 |
*/
|
166 |
protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
|
167 |
{
|
226 |
|
227 |
/**
|
228 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
|
|
|
|
|
|
229 |
*/
|
230 |
protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
|
231 |
{
|
library/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
CHANGED
@@ -51,7 +51,7 @@ class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor
|
|
51 |
|
52 |
// wrap print to check __toString() calls
|
53 |
if ($node instanceof Twig_Node_Print) {
|
54 |
-
return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->
|
55 |
}
|
56 |
}
|
57 |
|
51 |
|
52 |
// wrap print to check __toString() calls
|
53 |
if ($node instanceof Twig_Node_Print) {
|
54 |
+
return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag());
|
55 |
}
|
56 |
}
|
57 |
|
library/twig/twig/lib/Twig/NodeVisitorInterface.php
CHANGED
@@ -19,9 +19,6 @@ interface Twig_NodeVisitorInterface
|
|
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);
|
@@ -29,9 +26,6 @@ interface Twig_NodeVisitorInterface
|
|
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);
|
19 |
/**
|
20 |
* Called before child nodes are visited.
|
21 |
*
|
|
|
|
|
|
|
22 |
* @return Twig_NodeInterface The modified node
|
23 |
*/
|
24 |
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env);
|
26 |
/**
|
27 |
* Called after child nodes are visited.
|
28 |
*
|
|
|
|
|
|
|
29 |
* @return Twig_NodeInterface|false The modified node or false if the node must be removed
|
30 |
*/
|
31 |
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
|
library/twig/twig/lib/Twig/Parser.php
CHANGED
@@ -32,18 +32,18 @@ class Twig_Parser implements Twig_ParserInterface
|
|
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 |
|
@@ -52,9 +52,14 @@ class Twig_Parser implements Twig_ParserInterface
|
|
52 |
return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
|
53 |
}
|
54 |
|
|
|
|
|
|
|
55 |
public function getFilename()
|
56 |
{
|
57 |
-
|
|
|
|
|
58 |
}
|
59 |
|
60 |
/**
|
@@ -64,6 +69,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
64 |
{
|
65 |
// push all variables into the stack to keep the current state of the parser
|
66 |
// using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336
|
|
|
67 |
$vars = array();
|
68 |
foreach ($this as $k => $v) {
|
69 |
$vars[$k] = $v;
|
@@ -84,7 +90,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
84 |
}
|
85 |
|
86 |
if (null === $this->expressionParser) {
|
87 |
-
$this->expressionParser = new Twig_ExpressionParser($this, $this->env
|
88 |
}
|
89 |
|
90 |
$this->stream = $stream;
|
@@ -103,8 +109,8 @@ class Twig_Parser implements Twig_ParserInterface
|
|
103 |
$body = new Twig_Node();
|
104 |
}
|
105 |
} catch (Twig_Error_Syntax $e) {
|
106 |
-
if (!$e->
|
107 |
-
$e->
|
108 |
}
|
109 |
|
110 |
if (!$e->getTemplateLine()) {
|
@@ -114,7 +120,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
114 |
throw $e;
|
115 |
}
|
116 |
|
117 |
-
$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, $
|
118 |
|
119 |
$traverser = new Twig_NodeTraverser($this->env, $this->visitors);
|
120 |
|
@@ -151,7 +157,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
151 |
$token = $this->getCurrentToken();
|
152 |
|
153 |
if ($token->getType() !== Twig_Token::NAME_TYPE) {
|
154 |
-
throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->
|
155 |
}
|
156 |
|
157 |
if (null !== $test && call_user_func($test, $token)) {
|
@@ -169,13 +175,13 @@ class Twig_Parser implements Twig_ParserInterface
|
|
169 |
$subparser = $this->handlers->getTokenParser($token->getValue());
|
170 |
if (null === $subparser) {
|
171 |
if (null !== $test) {
|
172 |
-
$e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->
|
173 |
|
174 |
if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
|
175 |
$e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
|
176 |
}
|
177 |
} else {
|
178 |
-
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->
|
179 |
$e->addSuggestions($token->getValue(), array_keys($this->env->getTags()));
|
180 |
}
|
181 |
|
@@ -191,7 +197,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
191 |
break;
|
192 |
|
193 |
default:
|
194 |
-
throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->
|
195 |
}
|
196 |
}
|
197 |
|
@@ -202,13 +208,23 @@ class Twig_Parser implements Twig_ParserInterface
|
|
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 |
|
@@ -244,7 +260,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
244 |
|
245 |
public function setBlock($name, Twig_Node_Block $value)
|
246 |
{
|
247 |
-
$this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->
|
248 |
}
|
249 |
|
250 |
public function hasMacro($name)
|
@@ -255,7 +271,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
255 |
public function setMacro($name, Twig_Node_Macro $node)
|
256 |
{
|
257 |
if ($this->isReservedMacroName($name)) {
|
258 |
-
throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->
|
259 |
}
|
260 |
|
261 |
$this->macros[$name] = $node;
|
@@ -325,9 +341,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
325 |
}
|
326 |
|
327 |
/**
|
328 |
-
*
|
329 |
-
*
|
330 |
-
* @return Twig_ExpressionParser The expression parser
|
331 |
*/
|
332 |
public function getExpressionParser()
|
333 |
{
|
@@ -345,9 +359,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
345 |
}
|
346 |
|
347 |
/**
|
348 |
-
*
|
349 |
-
*
|
350 |
-
* @return Twig_TokenStream The token stream
|
351 |
*/
|
352 |
public function getStream()
|
353 |
{
|
@@ -355,9 +367,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
355 |
}
|
356 |
|
357 |
/**
|
358 |
-
*
|
359 |
-
*
|
360 |
-
* @return Twig_Token The current token
|
361 |
*/
|
362 |
public function getCurrentToken()
|
363 |
{
|
@@ -373,10 +383,10 @@ class Twig_Parser implements Twig_ParserInterface
|
|
373 |
(!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
|
374 |
) {
|
375 |
if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
|
376 |
-
throw new Twig_Error_Syntax('A template that extends another one cannot
|
377 |
}
|
378 |
|
379 |
-
throw new Twig_Error_Syntax('A template that extends another one cannot
|
380 |
}
|
381 |
|
382 |
// bypass "set" nodes as they "capture" the output
|
32 |
protected $traits;
|
33 |
protected $embeddedTemplates = array();
|
34 |
|
|
|
|
|
|
|
|
|
|
|
35 |
public function __construct(Twig_Environment $env)
|
36 |
{
|
37 |
$this->env = $env;
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
42 |
+
*/
|
43 |
public function getEnvironment()
|
44 |
{
|
45 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
|
46 |
+
|
47 |
return $this->env;
|
48 |
}
|
49 |
|
52 |
return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
|
53 |
}
|
54 |
|
55 |
+
/**
|
56 |
+
* @deprecated since 1.27 (to be removed in 2.0). Use $parser->getStream()->getSourceContext()->getPath() instead.
|
57 |
+
*/
|
58 |
public function getFilename()
|
59 |
{
|
60 |
+
@trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use $parser->getStream()->getSourceContext()->getPath() instead.', __METHOD__), E_USER_DEPRECATED);
|
61 |
+
|
62 |
+
return $this->stream->getSourceContext()->getName();
|
63 |
}
|
64 |
|
65 |
/**
|
69 |
{
|
70 |
// push all variables into the stack to keep the current state of the parser
|
71 |
// using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336
|
72 |
+
// This hack can be removed when min version if PHP 7.0
|
73 |
$vars = array();
|
74 |
foreach ($this as $k => $v) {
|
75 |
$vars[$k] = $v;
|
90 |
}
|
91 |
|
92 |
if (null === $this->expressionParser) {
|
93 |
+
$this->expressionParser = new Twig_ExpressionParser($this, $this->env);
|
94 |
}
|
95 |
|
96 |
$this->stream = $stream;
|
109 |
$body = new Twig_Node();
|
110 |
}
|
111 |
} catch (Twig_Error_Syntax $e) {
|
112 |
+
if (!$e->getTemplateName()) {
|
113 |
+
$e->setTemplateName($this->stream->getSourceContext()->getName());
|
114 |
}
|
115 |
|
116 |
if (!$e->getTemplateLine()) {
|
120 |
throw $e;
|
121 |
}
|
122 |
|
123 |
+
$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, $stream->getSourceContext());
|
124 |
|
125 |
$traverser = new Twig_NodeTraverser($this->env, $this->visitors);
|
126 |
|
157 |
$token = $this->getCurrentToken();
|
158 |
|
159 |
if ($token->getType() !== Twig_Token::NAME_TYPE) {
|
160 |
+
throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext()->getName());
|
161 |
}
|
162 |
|
163 |
if (null !== $test && call_user_func($test, $token)) {
|
175 |
$subparser = $this->handlers->getTokenParser($token->getValue());
|
176 |
if (null === $subparser) {
|
177 |
if (null !== $test) {
|
178 |
+
$e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()->getName());
|
179 |
|
180 |
if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
|
181 |
$e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
|
182 |
}
|
183 |
} else {
|
184 |
+
$e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()->getName());
|
185 |
$e->addSuggestions($token->getValue(), array_keys($this->env->getTags()));
|
186 |
}
|
187 |
|
197 |
break;
|
198 |
|
199 |
default:
|
200 |
+
throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->stream->getSourceContext()->getName());
|
201 |
}
|
202 |
}
|
203 |
|
208 |
return new Twig_Node($rv, array(), $lineno);
|
209 |
}
|
210 |
|
211 |
+
/**
|
212 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
213 |
+
*/
|
214 |
public function addHandler($name, $class)
|
215 |
{
|
216 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
|
217 |
+
|
218 |
$this->handlers[$name] = $class;
|
219 |
}
|
220 |
|
221 |
+
/**
|
222 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
223 |
+
*/
|
224 |
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
|
225 |
{
|
226 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
|
227 |
+
|
228 |
$this->visitors[] = $visitor;
|
229 |
}
|
230 |
|
260 |
|
261 |
public function setBlock($name, Twig_Node_Block $value)
|
262 |
{
|
263 |
+
$this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getTemplateLine());
|
264 |
}
|
265 |
|
266 |
public function hasMacro($name)
|
271 |
public function setMacro($name, Twig_Node_Macro $node)
|
272 |
{
|
273 |
if ($this->isReservedMacroName($name)) {
|
274 |
+
throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext()->getName());
|
275 |
}
|
276 |
|
277 |
$this->macros[$name] = $node;
|
341 |
}
|
342 |
|
343 |
/**
|
344 |
+
* @return Twig_ExpressionParser
|
|
|
|
|
345 |
*/
|
346 |
public function getExpressionParser()
|
347 |
{
|
359 |
}
|
360 |
|
361 |
/**
|
362 |
+
* @return Twig_TokenStream
|
|
|
|
|
363 |
*/
|
364 |
public function getStream()
|
365 |
{
|
367 |
}
|
368 |
|
369 |
/**
|
370 |
+
* @return Twig_Token
|
|
|
|
|
371 |
*/
|
372 |
public function getCurrentToken()
|
373 |
{
|
383 |
(!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
|
384 |
) {
|
385 |
if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
|
386 |
+
throw new Twig_Error_Syntax('A template that extends another one cannot start with a byte order mark (BOM); it must be removed.', $node->getTemplateLine(), $this->stream->getSourceContext()->getName());
|
387 |
}
|
388 |
|
389 |
+
throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext()->getName());
|
390 |
}
|
391 |
|
392 |
// bypass "set" nodes as they "capture" the output
|
library/twig/twig/lib/Twig/ParserInterface.php
CHANGED
@@ -21,9 +21,7 @@ interface Twig_ParserInterface
|
|
21 |
/**
|
22 |
* Converts a token stream to a node tree.
|
23 |
*
|
24 |
-
* @
|
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 |
*/
|
21 |
/**
|
22 |
* Converts a token stream to a node tree.
|
23 |
*
|
24 |
+
* @return Twig_Node_Module
|
|
|
|
|
25 |
*
|
26 |
* @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
|
27 |
*/
|
library/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php
CHANGED
@@ -36,7 +36,7 @@ class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor
|
|
36 |
{
|
37 |
if ($node instanceof Twig_Node_Module) {
|
38 |
$varName = $this->getVarName();
|
39 |
-
$node->setNode('display_start', new Twig_Node(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::TEMPLATE, $node->
|
40 |
$node->setNode('display_end', new Twig_Node(array(new Twig_Profiler_Node_LeaveProfile($varName), $node->getNode('display_end'))));
|
41 |
} elseif ($node instanceof Twig_Node_Block) {
|
42 |
$varName = $this->getVarName();
|
36 |
{
|
37 |
if ($node instanceof Twig_Node_Module) {
|
38 |
$varName = $this->getVarName();
|
39 |
+
$node->setNode('display_start', new Twig_Node(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start'))));
|
40 |
$node->setNode('display_end', new Twig_Node(array(new Twig_Profiler_Node_LeaveProfile($varName), $node->getNode('display_end'))));
|
41 |
} elseif ($node instanceof Twig_Node_Block) {
|
42 |
$varName = $this->getVarName();
|
library/twig/twig/lib/Twig/RuntimeLoaderInterface.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 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 |
+
* Creates runtime implementations for Twig elements (filters/functions/tests).
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*/
|
17 |
+
interface Twig_RuntimeLoaderInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Creates the runtime implementation of a Twig element (filter/function/test).
|
21 |
+
*
|
22 |
+
* @param string $class A runtime class
|
23 |
+
*
|
24 |
+
* @return object|null The runtime instance or null if the loader does not know how to create the runtime for this class
|
25 |
+
*/
|
26 |
+
public function load($class);
|
27 |
+
}
|
library/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 not allowed class method is used in a template.
|
14 |
+
*
|
15 |
+
* @author Kit Burton-Senior <mail@kitbs.com>
|
16 |
+
*/
|
17 |
+
class Twig_Sandbox_SecurityNotAllowedMethodError extends Twig_Sandbox_SecurityError
|
18 |
+
{
|
19 |
+
private $className;
|
20 |
+
private $methodName;
|
21 |
+
|
22 |
+
public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, Exception $previous = null)
|
23 |
+
{
|
24 |
+
parent::__construct($message, $lineno, $filename, $previous);
|
25 |
+
$this->className = $className;
|
26 |
+
$this->methodName = $methodName;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getClassName()
|
30 |
+
{
|
31 |
+
return $this->className;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function getMethodName()
|
35 |
+
{
|
36 |
+
return $this->methodName;
|
37 |
+
}
|
38 |
+
}
|
library/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 not allowed class property is used in a template.
|
14 |
+
*
|
15 |
+
* @author Kit Burton-Senior <mail@kitbs.com>
|
16 |
+
*/
|
17 |
+
class Twig_Sandbox_SecurityNotAllowedPropertyError extends Twig_Sandbox_SecurityError
|
18 |
+
{
|
19 |
+
private $className;
|
20 |
+
private $propertyName;
|
21 |
+
|
22 |
+
public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, Exception $previous = null)
|
23 |
+
{
|
24 |
+
parent::__construct($message, $lineno, $filename, $previous);
|
25 |
+
$this->className = $className;
|
26 |
+
$this->propertyName = $propertyName;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getClassName()
|
30 |
+
{
|
31 |
+
return $this->className;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function getPropertyName()
|
35 |
+
{
|
36 |
+
return $this->propertyName;
|
37 |
+
}
|
38 |
+
}
|
library/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
CHANGED
@@ -97,7 +97,8 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac
|
|
97 |
}
|
98 |
|
99 |
if (!$allowed) {
|
100 |
-
|
|
|
101 |
}
|
102 |
}
|
103 |
|
@@ -113,7 +114,8 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac
|
|
113 |
}
|
114 |
|
115 |
if (!$allowed) {
|
116 |
-
|
|
|
117 |
}
|
118 |
}
|
119 |
}
|
97 |
}
|
98 |
|
99 |
if (!$allowed) {
|
100 |
+
$class = get_class($obj);
|
101 |
+
throw new Twig_Sandbox_SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method);
|
102 |
}
|
103 |
}
|
104 |
|
114 |
}
|
115 |
|
116 |
if (!$allowed) {
|
117 |
+
$class = get_class($obj);
|
118 |
+
throw new Twig_Sandbox_SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property);
|
119 |
}
|
120 |
}
|
121 |
}
|
library/twig/twig/lib/Twig/Source.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 2016 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 |
+
* Holds information about a non-compiled Twig template.
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*/
|
17 |
+
class Twig_Source
|
18 |
+
{
|
19 |
+
private $code;
|
20 |
+
private $name;
|
21 |
+
private $path;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param string $code The template source code
|
25 |
+
* @param string $name The template logical name
|
26 |
+
* @param string $path The filesystem path of the template if any
|
27 |
+
*/
|
28 |
+
public function __construct($code, $name, $path = '')
|
29 |
+
{
|
30 |
+
$this->code = $code;
|
31 |
+
$this->name = $name;
|
32 |
+
$this->path = $path;
|
33 |
+
}
|
34 |
+
|
35 |
+
public function getCode()
|
36 |
+
{
|
37 |
+
return $this->code;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function getName()
|
41 |
+
{
|
42 |
+
return $this->name;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function getPath()
|
46 |
+
{
|
47 |
+
return $this->path;
|
48 |
+
}
|
49 |
+
}
|
library/twig/twig/lib/Twig/SourceContextLoaderInterface.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 2016 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 a getSourceContext() method for loaders.
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*
|
17 |
+
* @deprecated since 1.27 (to be removed in 3.0)
|
18 |
+
*/
|
19 |
+
interface Twig_SourceContextLoaderInterface
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* Returns the source context for a given template logical name.
|
23 |
+
*
|
24 |
+
* @param string $name The template logical name
|
25 |
+
*
|
26 |
+
* @return Twig_Source
|
27 |
+
*
|
28 |
+
* @throws Twig_Error_Loader When $name is not found
|
29 |
+
*/
|
30 |
+
public function getSourceContext($name);
|
31 |
+
}
|
library/twig/twig/lib/Twig/Template.php
CHANGED
@@ -13,10 +13,19 @@
|
|
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;
|
@@ -25,11 +34,6 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
25 |
protected $blocks = array();
|
26 |
protected $traits = array();
|
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;
|
@@ -49,18 +53,35 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
49 |
*
|
50 |
* @internal
|
51 |
*/
|
52 |
-
|
|
|
|
|
|
|
53 |
|
54 |
/**
|
55 |
* Returns the template source code.
|
56 |
*
|
57 |
* @return string The template source code
|
|
|
|
|
58 |
*/
|
59 |
public function getSource()
|
60 |
{
|
|
|
|
|
61 |
return '';
|
62 |
}
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
/**
|
65 |
* @deprecated since 1.20 (to be removed in 2.0)
|
66 |
*/
|
@@ -104,7 +125,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
104 |
$this->parents[$parent] = $this->loadTemplate($parent);
|
105 |
}
|
106 |
} catch (Twig_Error_Loader $e) {
|
107 |
-
$e->
|
108 |
$e->guess();
|
109 |
|
110 |
throw $e;
|
@@ -144,7 +165,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
144 |
} elseif (false !== $parent = $this->getParent($context)) {
|
145 |
$parent->displayBlock($name, $context, $blocks, false);
|
146 |
} else {
|
147 |
-
throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName());
|
148 |
}
|
149 |
}
|
150 |
|
@@ -185,8 +206,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
185 |
try {
|
186 |
$template->$block($context, $blocks);
|
187 |
} catch (Twig_Error $e) {
|
188 |
-
if (!$e->
|
189 |
-
$e->
|
190 |
}
|
191 |
|
192 |
// this is mostly useful for Twig_Error_Loader exceptions
|
@@ -251,44 +272,70 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
-
* Returns whether a block exists or not.
|
255 |
-
*
|
256 |
-
* This method is for internal use only and should never be called
|
257 |
-
* directly.
|
258 |
*
|
259 |
-
* This method
|
260 |
-
* or defined in "used" traits.
|
261 |
*
|
262 |
-
*
|
263 |
-
*
|
264 |
-
* current
|
265 |
-
*
|
266 |
-
* @param string $name The block name
|
267 |
*
|
268 |
* @return bool true if the block exists, false otherwise
|
269 |
*
|
270 |
* @internal
|
271 |
*/
|
272 |
-
public function hasBlock($name)
|
273 |
{
|
274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
}
|
276 |
|
277 |
/**
|
278 |
-
* Returns all block names.
|
279 |
*
|
280 |
-
* This method
|
281 |
-
*
|
282 |
*
|
283 |
-
* @
|
|
|
284 |
*
|
285 |
-
* @
|
286 |
*
|
287 |
* @internal
|
288 |
*/
|
289 |
-
public function getBlockNames()
|
290 |
{
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
}
|
293 |
|
294 |
protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
|
@@ -302,10 +349,14 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
302 |
return $template;
|
303 |
}
|
304 |
|
|
|
|
|
|
|
|
|
305 |
return $this->env->loadTemplate($template, $index);
|
306 |
} catch (Twig_Error $e) {
|
307 |
-
if (!$e->
|
308 |
-
$e->
|
309 |
}
|
310 |
|
311 |
if ($e->getTemplateLine()) {
|
@@ -330,8 +381,6 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
330 |
*
|
331 |
* @return array An array of blocks
|
332 |
*
|
333 |
-
* @see hasBlock
|
334 |
-
*
|
335 |
* @internal
|
336 |
*/
|
337 |
public function getBlocks()
|
@@ -378,8 +427,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
378 |
try {
|
379 |
$this->doDisplay($context, $blocks);
|
380 |
} catch (Twig_Error $e) {
|
381 |
-
if (!$e->
|
382 |
-
$e->
|
383 |
}
|
384 |
|
385 |
// this is mostly useful for Twig_Error_Loader exceptions
|
@@ -431,7 +480,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
431 |
return;
|
432 |
}
|
433 |
|
434 |
-
throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName());
|
435 |
}
|
436 |
|
437 |
return $context[$item];
|
@@ -450,6 +499,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
450 |
* @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
|
451 |
*
|
452 |
* @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
|
|
|
|
|
453 |
*/
|
454 |
protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
455 |
{
|
@@ -457,7 +508,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
457 |
if (self::METHOD_CALL !== $type) {
|
458 |
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
459 |
|
460 |
-
if ((is_array($object) && array_key_exists($arrayItem, $object))
|
461 |
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
462 |
) {
|
463 |
if ($isDefinedTest) {
|
@@ -477,25 +528,25 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
477 |
}
|
478 |
|
479 |
if ($object instanceof ArrayAccess) {
|
480 |
-
$message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist', $arrayItem, get_class($object));
|
481 |
} elseif (is_object($object)) {
|
482 |
-
$message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object));
|
483 |
} elseif (is_array($object)) {
|
484 |
if (empty($object)) {
|
485 |
-
$message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem);
|
486 |
} else {
|
487 |
-
$message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
|
488 |
}
|
489 |
} elseif (self::ARRAY_CALL === $type) {
|
490 |
if (null === $object) {
|
491 |
-
$message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
|
492 |
} else {
|
493 |
-
$message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
494 |
}
|
495 |
} elseif (null === $object) {
|
496 |
-
$message = sprintf('Impossible to access an attribute ("%s") on a null variable', $item);
|
497 |
} else {
|
498 |
-
$message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
499 |
}
|
500 |
|
501 |
throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
|
@@ -512,9 +563,9 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
512 |
}
|
513 |
|
514 |
if (null === $object) {
|
515 |
-
$message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item);
|
516 |
} else {
|
517 |
-
$message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
518 |
}
|
519 |
|
520 |
throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
|
@@ -527,8 +578,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
527 |
return true;
|
528 |
}
|
529 |
|
530 |
-
if ($this->env->hasExtension('
|
531 |
-
$this->env->getExtension('
|
532 |
}
|
533 |
|
534 |
return $object->$item;
|
@@ -538,37 +589,57 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
538 |
$class = get_class($object);
|
539 |
|
540 |
// object method
|
541 |
-
if (!isset(self::$cache[$class]
|
542 |
// get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
|
543 |
if ($object instanceof self) {
|
544 |
$ref = new ReflectionClass($class);
|
545 |
$methods = array();
|
546 |
|
547 |
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
548 |
-
$methodName = strtolower($refMethod->name);
|
549 |
-
|
550 |
// Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
|
551 |
-
if ('getenvironment' !== $
|
552 |
-
$methods[
|
553 |
}
|
554 |
}
|
555 |
-
|
556 |
-
self::$cache[$class]['methods'] = $methods;
|
557 |
} else {
|
558 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
559 |
}
|
|
|
560 |
}
|
561 |
|
562 |
$call = false;
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
$method = 'is'.$item;
|
570 |
-
} elseif (isset(self::$cache[$class]['methods']['__call'])) {
|
571 |
-
$method = (string) $item;
|
572 |
$call = true;
|
573 |
} else {
|
574 |
if ($isDefinedTest) {
|
@@ -579,21 +650,25 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
579 |
return;
|
580 |
}
|
581 |
|
582 |
-
throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s"', $item,
|
583 |
}
|
584 |
|
585 |
if ($isDefinedTest) {
|
586 |
return true;
|
587 |
}
|
588 |
|
589 |
-
if ($this->env->hasExtension('
|
590 |
-
$this->env->getExtension('
|
591 |
}
|
592 |
|
593 |
// Some objects throw exceptions when they have __call, and the method we try
|
594 |
// to call is not supported. If ignoreStrictCheck is true, we should return null.
|
595 |
try {
|
596 |
-
|
|
|
|
|
|
|
|
|
597 |
} catch (BadMethodCallException $e) {
|
598 |
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
599 |
return;
|
@@ -601,9 +676,19 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
601 |
throw $e;
|
602 |
}
|
603 |
|
604 |
-
//
|
605 |
-
// this is not supported but unfortunately heavily used in the Symfony profiler
|
606 |
if ($object instanceof Twig_TemplateInterface) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
607 |
return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
|
608 |
}
|
609 |
|
13 |
/**
|
14 |
* Default base class for compiled templates.
|
15 |
*
|
16 |
+
* This class is an implementation detail of how template compilation currently
|
17 |
+
* works, which might change. It should never be used directly. Use $twig->load()
|
18 |
+
* instead, which returns an instance of Twig_TemplateWrapper.
|
19 |
+
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
+
*
|
22 |
+
* @internal
|
23 |
*/
|
24 |
abstract class Twig_Template implements Twig_TemplateInterface
|
25 |
{
|
26 |
+
/**
|
27 |
+
* @internal
|
28 |
+
*/
|
29 |
protected static $cache = array();
|
30 |
|
31 |
protected $parent;
|
34 |
protected $blocks = array();
|
35 |
protected $traits = array();
|
36 |
|
|
|
|
|
|
|
|
|
|
|
37 |
public function __construct(Twig_Environment $env)
|
38 |
{
|
39 |
$this->env = $env;
|
53 |
*
|
54 |
* @internal
|
55 |
*/
|
56 |
+
public function getDebugInfo()
|
57 |
+
{
|
58 |
+
return array();
|
59 |
+
}
|
60 |
|
61 |
/**
|
62 |
* Returns the template source code.
|
63 |
*
|
64 |
* @return string The template source code
|
65 |
+
*
|
66 |
+
* @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead
|
67 |
*/
|
68 |
public function getSource()
|
69 |
{
|
70 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);
|
71 |
+
|
72 |
return '';
|
73 |
}
|
74 |
|
75 |
+
/**
|
76 |
+
* Returns information about the original template source code.
|
77 |
+
*
|
78 |
+
* @return Twig_Source
|
79 |
+
*/
|
80 |
+
public function getSourceContext()
|
81 |
+
{
|
82 |
+
return new Twig_Source('', $this->getTemplateName());
|
83 |
+
}
|
84 |
+
|
85 |
/**
|
86 |
* @deprecated since 1.20 (to be removed in 2.0)
|
87 |
*/
|
125 |
$this->parents[$parent] = $this->loadTemplate($parent);
|
126 |
}
|
127 |
} catch (Twig_Error_Loader $e) {
|
128 |
+
$e->setTemplateName(null);
|
129 |
$e->guess();
|
130 |
|
131 |
throw $e;
|
165 |
} elseif (false !== $parent = $this->getParent($context)) {
|
166 |
$parent->displayBlock($name, $context, $blocks, false);
|
167 |
} else {
|
168 |
+
throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getTemplateName());
|
169 |
}
|
170 |
}
|
171 |
|
206 |
try {
|
207 |
$template->$block($context, $blocks);
|
208 |
} catch (Twig_Error $e) {
|
209 |
+
if (!$e->getTemplateName()) {
|
210 |
+
$e->setTemplateName($template->getTemplateName());
|
211 |
}
|
212 |
|
213 |
// this is mostly useful for Twig_Error_Loader exceptions
|
272 |
}
|
273 |
|
274 |
/**
|
275 |
+
* Returns whether a block exists or not in the current context of the template.
|
|
|
|
|
|
|
276 |
*
|
277 |
+
* This method checks blocks defined in the current template
|
278 |
+
* or defined in "used" traits or defined in parent templates.
|
279 |
*
|
280 |
+
* @param string $name The block name
|
281 |
+
* @param array $context The context
|
282 |
+
* @param array $blocks The current set of blocks
|
|
|
|
|
283 |
*
|
284 |
* @return bool true if the block exists, false otherwise
|
285 |
*
|
286 |
* @internal
|
287 |
*/
|
288 |
+
public function hasBlock($name, array $context = null, array $blocks = array())
|
289 |
{
|
290 |
+
if (null === $context) {
|
291 |
+
@trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED);
|
292 |
+
|
293 |
+
return isset($this->blocks[(string) $name]);
|
294 |
+
}
|
295 |
+
|
296 |
+
if (isset($blocks[$name])) {
|
297 |
+
return $blocks[$name][0] instanceof self;
|
298 |
+
}
|
299 |
+
|
300 |
+
if (isset($this->blocks[$name])) {
|
301 |
+
return true;
|
302 |
+
}
|
303 |
+
|
304 |
+
if (false !== $parent = $this->getParent($context)) {
|
305 |
+
return $parent->hasBlock($name, $context);
|
306 |
+
}
|
307 |
+
|
308 |
+
return false;
|
309 |
}
|
310 |
|
311 |
/**
|
312 |
+
* Returns all block names in the current context of the template.
|
313 |
*
|
314 |
+
* This method checks blocks defined in the current template
|
315 |
+
* or defined in "used" traits or defined in parent templates.
|
316 |
*
|
317 |
+
* @param array $context The context
|
318 |
+
* @param array $blocks The current set of blocks
|
319 |
*
|
320 |
+
* @return array An array of block names
|
321 |
*
|
322 |
* @internal
|
323 |
*/
|
324 |
+
public function getBlockNames(array $context = null, array $blocks = array())
|
325 |
{
|
326 |
+
if (null === $context) {
|
327 |
+
@trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED);
|
328 |
+
|
329 |
+
return array_keys($this->blocks);
|
330 |
+
}
|
331 |
+
|
332 |
+
$names = array_merge(array_keys($blocks), array_keys($this->blocks));
|
333 |
+
|
334 |
+
if (false !== $parent = $this->getParent($context)) {
|
335 |
+
$names = array_merge($names, $parent->getBlockNames($context));
|
336 |
+
}
|
337 |
+
|
338 |
+
return array_unique($names);
|
339 |
}
|
340 |
|
341 |
protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
|
349 |
return $template;
|
350 |
}
|
351 |
|
352 |
+
if ($template instanceof Twig_TemplateWrapper) {
|
353 |
+
return $template;
|
354 |
+
}
|
355 |
+
|
356 |
return $this->env->loadTemplate($template, $index);
|
357 |
} catch (Twig_Error $e) {
|
358 |
+
if (!$e->getTemplateName()) {
|
359 |
+
$e->setTemplateName($templateName ? $templateName : $this->getTemplateName());
|
360 |
}
|
361 |
|
362 |
if ($e->getTemplateLine()) {
|
381 |
*
|
382 |
* @return array An array of blocks
|
383 |
*
|
|
|
|
|
384 |
* @internal
|
385 |
*/
|
386 |
public function getBlocks()
|
427 |
try {
|
428 |
$this->doDisplay($context, $blocks);
|
429 |
} catch (Twig_Error $e) {
|
430 |
+
if (!$e->getTemplateName()) {
|
431 |
+
$e->setTemplateName($this->getTemplateName());
|
432 |
}
|
433 |
|
434 |
// this is mostly useful for Twig_Error_Loader exceptions
|
480 |
return;
|
481 |
}
|
482 |
|
483 |
+
throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist.', $item), -1, $this->getTemplateName());
|
484 |
}
|
485 |
|
486 |
return $context[$item];
|
499 |
* @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
|
500 |
*
|
501 |
* @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
|
502 |
+
*
|
503 |
+
* @internal
|
504 |
*/
|
505 |
protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
506 |
{
|
508 |
if (self::METHOD_CALL !== $type) {
|
509 |
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
510 |
|
511 |
+
if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object)))
|
512 |
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
513 |
) {
|
514 |
if ($isDefinedTest) {
|
528 |
}
|
529 |
|
530 |
if ($object instanceof ArrayAccess) {
|
531 |
+
$message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, get_class($object));
|
532 |
} elseif (is_object($object)) {
|
533 |
+
$message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, get_class($object));
|
534 |
} elseif (is_array($object)) {
|
535 |
if (empty($object)) {
|
536 |
+
$message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem);
|
537 |
} else {
|
538 |
+
$message = sprintf('Key "%s" for array with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object)));
|
539 |
}
|
540 |
} elseif (self::ARRAY_CALL === $type) {
|
541 |
if (null === $object) {
|
542 |
+
$message = sprintf('Impossible to access a key ("%s") on a null variable.', $item);
|
543 |
} else {
|
544 |
+
$message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
|
545 |
}
|
546 |
} elseif (null === $object) {
|
547 |
+
$message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item);
|
548 |
} else {
|
549 |
+
$message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
|
550 |
}
|
551 |
|
552 |
throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
|
563 |
}
|
564 |
|
565 |
if (null === $object) {
|
566 |
+
$message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item);
|
567 |
} else {
|
568 |
+
$message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
|
569 |
}
|
570 |
|
571 |
throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
|
578 |
return true;
|
579 |
}
|
580 |
|
581 |
+
if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
|
582 |
+
$this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item);
|
583 |
}
|
584 |
|
585 |
return $object->$item;
|
589 |
$class = get_class($object);
|
590 |
|
591 |
// object method
|
592 |
+
if (!isset(self::$cache[$class])) {
|
593 |
// get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
|
594 |
if ($object instanceof self) {
|
595 |
$ref = new ReflectionClass($class);
|
596 |
$methods = array();
|
597 |
|
598 |
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
|
|
|
|
599 |
// Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
|
600 |
+
if ('getenvironment' !== strtolower($refMethod->name)) {
|
601 |
+
$methods[] = $refMethod->name;
|
602 |
}
|
603 |
}
|
|
|
|
|
604 |
} else {
|
605 |
+
$methods = get_class_methods($object);
|
606 |
+
}
|
607 |
+
// sort values to have consistent behavior, so that "get" methods win precedence over "is" methods
|
608 |
+
sort($methods);
|
609 |
+
|
610 |
+
$cache = array();
|
611 |
+
|
612 |
+
foreach ($methods as $method) {
|
613 |
+
$cache[$method] = $method;
|
614 |
+
$cache[$lcName = strtolower($method)] = $method;
|
615 |
+
|
616 |
+
if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) {
|
617 |
+
$name = substr($method, 3);
|
618 |
+
$lcName = substr($lcName, 3);
|
619 |
+
} elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) {
|
620 |
+
$name = substr($method, 2);
|
621 |
+
$lcName = substr($lcName, 2);
|
622 |
+
} else {
|
623 |
+
continue;
|
624 |
+
}
|
625 |
+
|
626 |
+
if (!isset($cache[$name])) {
|
627 |
+
$cache[$name] = $method;
|
628 |
+
}
|
629 |
+
if (!isset($cache[$lcName])) {
|
630 |
+
$cache[$lcName] = $method;
|
631 |
+
}
|
632 |
}
|
633 |
+
self::$cache[$class] = $cache;
|
634 |
}
|
635 |
|
636 |
$call = false;
|
637 |
+
if (isset(self::$cache[$class][$item])) {
|
638 |
+
$method = self::$cache[$class][$item];
|
639 |
+
} elseif (isset(self::$cache[$class][$lcItem = strtolower($item)])) {
|
640 |
+
$method = self::$cache[$class][$lcItem];
|
641 |
+
} elseif (isset(self::$cache[$class]['__call'])) {
|
642 |
+
$method = $item;
|
|
|
|
|
|
|
643 |
$call = true;
|
644 |
} else {
|
645 |
if ($isDefinedTest) {
|
650 |
return;
|
651 |
}
|
652 |
|
653 |
+
throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $this->getTemplateName());
|
654 |
}
|
655 |
|
656 |
if ($isDefinedTest) {
|
657 |
return true;
|
658 |
}
|
659 |
|
660 |
+
if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
|
661 |
+
$this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method);
|
662 |
}
|
663 |
|
664 |
// Some objects throw exceptions when they have __call, and the method we try
|
665 |
// to call is not supported. If ignoreStrictCheck is true, we should return null.
|
666 |
try {
|
667 |
+
if (!$arguments) {
|
668 |
+
$ret = $object->$method();
|
669 |
+
} else {
|
670 |
+
$ret = call_user_func_array(array($object, $method), $arguments);
|
671 |
+
}
|
672 |
} catch (BadMethodCallException $e) {
|
673 |
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
674 |
return;
|
676 |
throw $e;
|
677 |
}
|
678 |
|
679 |
+
// @deprecated in 1.28
|
|
|
680 |
if ($object instanceof Twig_TemplateInterface) {
|
681 |
+
$self = $object->getTemplateName() === $this->getTemplateName();
|
682 |
+
$message = sprintf('Calling "%s" on template "%s" from template "%s" is deprecated since version 1.28 and won\'t be supported anymore in 2.0.', $method, $object->getTemplateName(), $this->getTemplateName());
|
683 |
+
if ('renderBlock' === $method || 'displayBlock' === $method) {
|
684 |
+
$message .= sprintf(' Use block("%s"%s) instead).', $arguments[0], $self ? '' : ', template');
|
685 |
+
} elseif ('hasBlock' === $method) {
|
686 |
+
$message .= sprintf(' Use "block("%s"%s) is defined" instead).', $arguments[0], $self ? '' : ', template');
|
687 |
+
} elseif ('render' === $method || 'display' === $method) {
|
688 |
+
$message .= sprintf(' Use include("%s") instead).', $object->getTemplateName());
|
689 |
+
}
|
690 |
+
@trigger_error($message, E_USER_DEPRECATED);
|
691 |
+
|
692 |
return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
|
693 |
}
|
694 |
|
library/twig/twig/lib/Twig/TemplateInterface.php
CHANGED
@@ -42,7 +42,7 @@ interface Twig_TemplateInterface
|
|
42 |
/**
|
43 |
* Returns the bound environment for this template.
|
44 |
*
|
45 |
-
* @return Twig_Environment
|
46 |
*/
|
47 |
public function getEnvironment();
|
48 |
}
|
42 |
/**
|
43 |
* Returns the bound environment for this template.
|
44 |
*
|
45 |
+
* @return Twig_Environment
|
46 |
*/
|
47 |
public function getEnvironment();
|
48 |
}
|
library/twig/twig/lib/Twig/TemplateWrapper.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 2016 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 |
+
* Exposes a template to userland.
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*/
|
17 |
+
final class Twig_TemplateWrapper
|
18 |
+
{
|
19 |
+
private $env;
|
20 |
+
private $template;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* This method is for internal use only and should never be called
|
24 |
+
* directly (use Twig_Environment::load() instead).
|
25 |
+
*
|
26 |
+
* @internal
|
27 |
+
*/
|
28 |
+
public function __construct(Twig_Environment $env, Twig_Template $template)
|
29 |
+
{
|
30 |
+
$this->env = $env;
|
31 |
+
$this->template = $template;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Renders the template.
|
36 |
+
*
|
37 |
+
* @param array $context An array of parameters to pass to the template
|
38 |
+
*
|
39 |
+
* @return string The rendered template
|
40 |
+
*/
|
41 |
+
public function render($context = array())
|
42 |
+
{
|
43 |
+
return $this->template->render($context);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Displays the template.
|
48 |
+
*
|
49 |
+
* @param array $context An array of parameters to pass to the template
|
50 |
+
*/
|
51 |
+
public function display($context = array())
|
52 |
+
{
|
53 |
+
$this->template->display($context);
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Checks if a block is defined.
|
58 |
+
*
|
59 |
+
* @param string $name The block name
|
60 |
+
* @param array $context An array of parameters to pass to the template
|
61 |
+
*
|
62 |
+
* @return bool
|
63 |
+
*/
|
64 |
+
public function hasBlock($name, $context = array())
|
65 |
+
{
|
66 |
+
return $this->template->hasBlock($name, $context);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Returns defined block names in the template.
|
71 |
+
*
|
72 |
+
* @param array $context An array of parameters to pass to the template
|
73 |
+
*
|
74 |
+
* @return string[] An array of defined template block names
|
75 |
+
*/
|
76 |
+
public function getBlockNames($context = array())
|
77 |
+
{
|
78 |
+
return $this->template->getBlockNames($context);
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Renders a template block.
|
83 |
+
*
|
84 |
+
* @param string $name The block name to render
|
85 |
+
* @param array $context An array of parameters to pass to the template
|
86 |
+
*
|
87 |
+
* @return string The rendered block
|
88 |
+
*/
|
89 |
+
public function renderBlock($name, $context = array())
|
90 |
+
{
|
91 |
+
$context = $this->env->mergeGlobals($context);
|
92 |
+
$level = ob_get_level();
|
93 |
+
ob_start();
|
94 |
+
try {
|
95 |
+
$this->template->displayBlock($name, $context);
|
96 |
+
} catch (Exception $e) {
|
97 |
+
while (ob_get_level() > $level) {
|
98 |
+
ob_end_clean();
|
99 |
+
}
|
100 |
+
|
101 |
+
throw $e;
|
102 |
+
} catch (Throwable $e) {
|
103 |
+
while (ob_get_level() > $level) {
|
104 |
+
ob_end_clean();
|
105 |
+
}
|
106 |
+
|
107 |
+
throw $e;
|
108 |
+
}
|
109 |
+
|
110 |
+
return ob_get_clean();
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Displays a template block.
|
115 |
+
*
|
116 |
+
* @param string $name The block name to render
|
117 |
+
* @param array $context An array of parameters to pass to the template
|
118 |
+
*/
|
119 |
+
public function displayBlock($name, $context = array())
|
120 |
+
{
|
121 |
+
$this->template->displayBlock($name, $this->env->mergeGlobals($context));
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* @return Twig_Source
|
126 |
+
*/
|
127 |
+
public function getSourceContext()
|
128 |
+
{
|
129 |
+
return $this->template->getSourceContext();
|
130 |
+
}
|
131 |
+
}
|
library/twig/twig/lib/Twig/Test/IntegrationTestCase.php
CHANGED
@@ -167,13 +167,14 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
|
167 |
if (false !== $exception) {
|
168 |
$message = $e->getMessage();
|
169 |
$this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $message)));
|
170 |
-
$
|
|
|
171 |
|
172 |
return;
|
173 |
}
|
174 |
|
175 |
if ($e instanceof Twig_Error_Syntax) {
|
176 |
-
$e->
|
177 |
|
178 |
throw $e;
|
179 |
}
|
@@ -191,7 +192,7 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
|
191 |
}
|
192 |
|
193 |
if ($e instanceof Twig_Error_Syntax) {
|
194 |
-
$e->
|
195 |
} else {
|
196 |
$e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
|
197 |
}
|
@@ -211,8 +212,13 @@ abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
|
|
211 |
|
212 |
foreach (array_keys($templates) as $name) {
|
213 |
echo "Template: $name\n";
|
214 |
-
$
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
216 |
}
|
217 |
}
|
218 |
$this->assertEquals($expected, $output, $message.' (in '.$file.')');
|
167 |
if (false !== $exception) {
|
168 |
$message = $e->getMessage();
|
169 |
$this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $message)));
|
170 |
+
$last = substr($message, strlen($message) - 1);
|
171 |
+
$this->assertTrue('.' === $last || '?' === $last, $message, 'Exception message must end with a dot or a question mark.');
|
172 |
|
173 |
return;
|
174 |
}
|
175 |
|
176 |
if ($e instanceof Twig_Error_Syntax) {
|
177 |
+
$e->setTemplateName($file);
|
178 |
|
179 |
throw $e;
|
180 |
}
|
192 |
}
|
193 |
|
194 |
if ($e instanceof Twig_Error_Syntax) {
|
195 |
+
$e->setTemplateName($file);
|
196 |
} else {
|
197 |
$e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
|
198 |
}
|
212 |
|
213 |
foreach (array_keys($templates) as $name) {
|
214 |
echo "Template: $name\n";
|
215 |
+
$loader = $twig->getLoader();
|
216 |
+
if (!$loader instanceof Twig_SourceContextLoaderInterface) {
|
217 |
+
$source = new Twig_Source($loader->getSource($name), $name);
|
218 |
+
} else {
|
219 |
+
$source = $loader->getSourceContext($name);
|
220 |
+
}
|
221 |
+
echo $twig->compile($twig->parse($twig->tokenize($source)));
|
222 |
}
|
223 |
}
|
224 |
$this->assertEquals($expected, $output, $message.' (in '.$file.')');
|
library/twig/twig/lib/Twig/Test/Method.php
CHANGED
@@ -35,6 +35,6 @@ class Twig_Test_Method extends Twig_Test
|
|
35 |
|
36 |
public function compile()
|
37 |
{
|
38 |
-
return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension
|
39 |
}
|
40 |
}
|
35 |
|
36 |
public function compile()
|
37 |
{
|
38 |
+
return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
|
39 |
}
|
40 |
}
|
library/twig/twig/lib/Twig/Test/NodeTestCase.php
CHANGED
@@ -46,6 +46,10 @@ abstract class Twig_Test_NodeTestCase extends PHPUnit_Framework_TestCase
|
|
46 |
{
|
47 |
$line = $line > 0 ? "// line {$line}\n" : '';
|
48 |
|
|
|
|
|
|
|
|
|
49 |
if (PHP_VERSION_ID >= 50400) {
|
50 |
return sprintf('%s(isset($context["%s"]) ? $context["%s"] : null)', $line, $name, $name);
|
51 |
}
|
46 |
{
|
47 |
$line = $line > 0 ? "// line {$line}\n" : '';
|
48 |
|
49 |
+
if (PHP_VERSION_ID >= 70000) {
|
50 |
+
return sprintf('%s($context["%s"] ?? null)', $line, $name, $name);
|
51 |
+
}
|
52 |
+
|
53 |
if (PHP_VERSION_ID >= 50400) {
|
54 |
return sprintf('%s(isset($context["%s"]) ? $context["%s"] : null)', $line, $name, $name);
|
55 |
}
|
library/twig/twig/lib/Twig/Token.php
CHANGED
@@ -36,8 +36,6 @@ class Twig_Token
|
|
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
|
@@ -49,11 +47,6 @@ class Twig_Token
|
|
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);
|
@@ -63,9 +56,9 @@ class Twig_Token
|
|
63 |
* Tests the current token for a type and/or a value.
|
64 |
*
|
65 |
* Parameters may be:
|
66 |
-
*
|
67 |
-
*
|
68 |
-
*
|
69 |
*
|
70 |
* @param array|int $type The type to test
|
71 |
* @param array|string|null $values The token value
|
@@ -87,9 +80,7 @@ class Twig_Token
|
|
87 |
}
|
88 |
|
89 |
/**
|
90 |
-
*
|
91 |
-
*
|
92 |
-
* @return int The source line
|
93 |
*/
|
94 |
public function getLine()
|
95 |
{
|
@@ -97,9 +88,7 @@ class Twig_Token
|
|
97 |
}
|
98 |
|
99 |
/**
|
100 |
-
*
|
101 |
-
*
|
102 |
-
* @return int The token type
|
103 |
*/
|
104 |
public function getType()
|
105 |
{
|
@@ -107,9 +96,7 @@ class Twig_Token
|
|
107 |
}
|
108 |
|
109 |
/**
|
110 |
-
*
|
111 |
-
*
|
112 |
-
* @return string The token value
|
113 |
*/
|
114 |
public function getValue()
|
115 |
{
|
@@ -174,7 +161,7 @@ class Twig_Token
|
|
174 |
}
|
175 |
|
176 |
/**
|
177 |
-
* Returns the
|
178 |
*
|
179 |
* @param int $type The type as an integer
|
180 |
*
|
36 |
const INTERPOLATION_END_TYPE = 11;
|
37 |
|
38 |
/**
|
|
|
|
|
39 |
* @param int $type The type of the token
|
40 |
* @param string $value The token value
|
41 |
* @param int $lineno The line position in the source
|
47 |
$this->lineno = $lineno;
|
48 |
}
|
49 |
|
|
|
|
|
|
|
|
|
|
|
50 |
public function __toString()
|
51 |
{
|
52 |
return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value);
|
56 |
* Tests the current token for a type and/or a value.
|
57 |
*
|
58 |
* Parameters may be:
|
59 |
+
* * just type
|
60 |
+
* * type and value (or array of possible values)
|
61 |
+
* * just value (or array of possible values) (NAME_TYPE is used as type)
|
62 |
*
|
63 |
* @param array|int $type The type to test
|
64 |
* @param array|string|null $values The token value
|
80 |
}
|
81 |
|
82 |
/**
|
83 |
+
* @return int
|
|
|
|
|
84 |
*/
|
85 |
public function getLine()
|
86 |
{
|
88 |
}
|
89 |
|
90 |
/**
|
91 |
+
* @return int
|
|
|
|
|
92 |
*/
|
93 |
public function getType()
|
94 |
{
|
96 |
}
|
97 |
|
98 |
/**
|
99 |
+
* @return string
|
|
|
|
|
100 |
*/
|
101 |
public function getValue()
|
102 |
{
|
161 |
}
|
162 |
|
163 |
/**
|
164 |
+
* Returns the English representation of a given type.
|
165 |
*
|
166 |
* @param int $type The type as an integer
|
167 |
*
|
library/twig/twig/lib/Twig/TokenParser.php
CHANGED
@@ -23,8 +23,6 @@ abstract class Twig_TokenParser implements Twig_TokenParserInterface
|
|
23 |
|
24 |
/**
|
25 |
* Sets the parser associated with this token parser.
|
26 |
-
*
|
27 |
-
* @param Twig_Parser $parser A Twig_Parser instance
|
28 |
*/
|
29 |
public function setParser(Twig_Parser $parser)
|
30 |
{
|
23 |
|
24 |
/**
|
25 |
* Sets the parser associated with this token parser.
|
|
|
|
|
26 |
*/
|
27 |
public function setParser(Twig_Parser $parser)
|
28 |
{
|
library/twig/twig/lib/Twig/TokenParser/AutoEscape.php
CHANGED
@@ -39,7 +39,7 @@ class Twig_TokenParser_AutoEscape extends Twig_TokenParser
|
|
39 |
} else {
|
40 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
41 |
if (!$expr instanceof Twig_Node_Expression_Constant) {
|
42 |
-
throw new Twig_Error_Syntax('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->
|
43 |
}
|
44 |
$value = $expr->getAttribute('value');
|
45 |
|
@@ -53,7 +53,7 @@ class Twig_TokenParser_AutoEscape extends Twig_TokenParser
|
|
53 |
@trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED);
|
54 |
|
55 |
if (false === $value) {
|
56 |
-
throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->
|
57 |
}
|
58 |
|
59 |
$value = $stream->next()->getValue();
|
39 |
} else {
|
40 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
41 |
if (!$expr instanceof Twig_Node_Expression_Constant) {
|
42 |
+
throw new Twig_Error_Syntax('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
43 |
}
|
44 |
$value = $expr->getAttribute('value');
|
45 |
|
53 |
@trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED);
|
54 |
|
55 |
if (false === $value) {
|
56 |
+
throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
57 |
}
|
58 |
|
59 |
$value = $stream->next()->getValue();
|
library/twig/twig/lib/Twig/TokenParser/Block.php
CHANGED
@@ -28,7 +28,7 @@ class Twig_TokenParser_Block extends Twig_TokenParser
|
|
28 |
$stream = $this->parser->getStream();
|
29 |
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
30 |
if ($this->parser->hasBlock($name)) {
|
31 |
-
throw new Twig_Error_Syntax(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->
|
32 |
}
|
33 |
$this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno));
|
34 |
$this->parser->pushLocalScope();
|
@@ -40,7 +40,7 @@ class Twig_TokenParser_Block extends Twig_TokenParser
|
|
40 |
$value = $token->getValue();
|
41 |
|
42 |
if ($value != $name) {
|
43 |
-
throw new Twig_Error_Syntax(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->
|
44 |
}
|
45 |
}
|
46 |
} else {
|
28 |
$stream = $this->parser->getStream();
|
29 |
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
30 |
if ($this->parser->hasBlock($name)) {
|
31 |
+
throw new Twig_Error_Syntax(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
32 |
}
|
33 |
$this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno));
|
34 |
$this->parser->pushLocalScope();
|
40 |
$value = $token->getValue();
|
41 |
|
42 |
if ($value != $name) {
|
43 |
+
throw new Twig_Error_Syntax(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
44 |
}
|
45 |
}
|
46 |
} else {
|
library/twig/twig/lib/Twig/TokenParser/Embed.php
CHANGED
@@ -48,7 +48,7 @@ class Twig_TokenParser_Embed extends Twig_TokenParser_Include
|
|
48 |
|
49 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
50 |
|
51 |
-
return new Twig_Node_Embed($module->
|
52 |
}
|
53 |
|
54 |
public function decideBlockEnd(Twig_Token $token)
|
48 |
|
49 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
50 |
|
51 |
+
return new Twig_Node_Embed($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
|
52 |
}
|
53 |
|
54 |
public function decideBlockEnd(Twig_Token $token)
|
library/twig/twig/lib/Twig/TokenParser/Extends.php
CHANGED
@@ -21,16 +21,18 @@ class Twig_TokenParser_Extends extends Twig_TokenParser
|
|
21 |
{
|
22 |
public function parse(Twig_Token $token)
|
23 |
{
|
|
|
|
|
24 |
if (!$this->parser->isMainScope()) {
|
25 |
-
throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $
|
26 |
}
|
27 |
|
28 |
if (null !== $this->parser->getParent()) {
|
29 |
-
throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $
|
30 |
}
|
31 |
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
32 |
|
33 |
-
$
|
34 |
}
|
35 |
|
36 |
public function getTag()
|
21 |
{
|
22 |
public function parse(Twig_Token $token)
|
23 |
{
|
24 |
+
$stream = $this->parser->getStream();
|
25 |
+
|
26 |
if (!$this->parser->isMainScope()) {
|
27 |
+
throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $stream->getSourceContext()->getName());
|
28 |
}
|
29 |
|
30 |
if (null !== $this->parser->getParent()) {
|
31 |
+
throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext()->getName());
|
32 |
}
|
33 |
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
34 |
|
35 |
+
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
36 |
}
|
37 |
|
38 |
public function getTag()
|
library/twig/twig/lib/Twig/TokenParser/Filter.php
CHANGED
@@ -23,7 +23,7 @@ class Twig_TokenParser_Filter extends Twig_TokenParser
|
|
23 |
public function parse(Twig_Token $token)
|
24 |
{
|
25 |
$name = $this->parser->getVarName();
|
26 |
-
$ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()),
|
27 |
|
28 |
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
|
29 |
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
23 |
public function parse(Twig_Token $token)
|
24 |
{
|
25 |
$name = $this->parser->getVarName();
|
26 |
+
$ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), null, $token->getLine(), $this->getTag());
|
27 |
|
28 |
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
|
29 |
$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
|
library/twig/twig/lib/Twig/TokenParser/For.php
CHANGED
@@ -48,13 +48,13 @@ class Twig_TokenParser_For extends Twig_TokenParser
|
|
48 |
|
49 |
if (count($targets) > 1) {
|
50 |
$keyTarget = $targets->getNode(0);
|
51 |
-
$keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->
|
52 |
$valueTarget = $targets->getNode(1);
|
53 |
-
$valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->
|
54 |
} else {
|
55 |
$keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
|
56 |
$valueTarget = $targets->getNode(0);
|
57 |
-
$valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->
|
58 |
}
|
59 |
|
60 |
if ($ifexpr) {
|
@@ -79,7 +79,7 @@ class Twig_TokenParser_For extends Twig_TokenParser
|
|
79 |
protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
|
80 |
{
|
81 |
if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
|
82 |
-
throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition.', $node->
|
83 |
}
|
84 |
|
85 |
foreach ($node as $n) {
|
@@ -98,7 +98,7 @@ class Twig_TokenParser_For extends Twig_TokenParser
|
|
98 |
if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
|
99 |
$attribute = $node->getNode('attribute');
|
100 |
if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
|
101 |
-
throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->
|
102 |
}
|
103 |
}
|
104 |
|
48 |
|
49 |
if (count($targets) > 1) {
|
50 |
$keyTarget = $targets->getNode(0);
|
51 |
+
$keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine());
|
52 |
$valueTarget = $targets->getNode(1);
|
53 |
+
$valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
|
54 |
} else {
|
55 |
$keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
|
56 |
$valueTarget = $targets->getNode(0);
|
57 |
+
$valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
|
58 |
}
|
59 |
|
60 |
if ($ifexpr) {
|
79 |
protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
|
80 |
{
|
81 |
if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
|
82 |
+
throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext()->getName());
|
83 |
}
|
84 |
|
85 |
foreach ($node as $n) {
|
98 |
if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
|
99 |
$attribute = $node->getNode('attribute');
|
100 |
if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
|
101 |
+
throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext()->getName());
|
102 |
}
|
103 |
}
|
104 |
|
library/twig/twig/lib/Twig/TokenParser/From.php
CHANGED
@@ -46,7 +46,7 @@ class Twig_TokenParser_From extends Twig_TokenParser
|
|
46 |
|
47 |
foreach ($targets as $name => $alias) {
|
48 |
if ($this->parser->isReservedMacroName($name)) {
|
49 |
-
throw new Twig_Error_Syntax(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->
|
50 |
}
|
51 |
|
52 |
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
46 |
|
47 |
foreach ($targets as $name => $alias) {
|
48 |
if ($this->parser->isReservedMacroName($name)) {
|
49 |
+
throw new Twig_Error_Syntax(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()->getName());
|
50 |
}
|
51 |
|
52 |
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
library/twig/twig/lib/Twig/TokenParser/If.php
CHANGED
@@ -56,7 +56,7 @@ class Twig_TokenParser_If extends Twig_TokenParser
|
|
56 |
break;
|
57 |
|
58 |
default:
|
59 |
-
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->
|
60 |
}
|
61 |
}
|
62 |
|
56 |
break;
|
57 |
|
58 |
default:
|
59 |
+
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->getSourceContext()->getName());
|
60 |
}
|
61 |
}
|
62 |
|
library/twig/twig/lib/Twig/TokenParser/Macro.php
CHANGED
@@ -35,7 +35,7 @@ class Twig_TokenParser_Macro extends Twig_TokenParser
|
|
35 |
$value = $token->getValue();
|
36 |
|
37 |
if ($value != $name) {
|
38 |
-
throw new Twig_Error_Syntax(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->
|
39 |
}
|
40 |
}
|
41 |
$this->parser->popLocalScope();
|
35 |
$value = $token->getValue();
|
36 |
|
37 |
if ($value != $name) {
|
38 |
+
throw new Twig_Error_Syntax(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
39 |
}
|
40 |
}
|
41 |
$this->parser->popLocalScope();
|
library/twig/twig/lib/Twig/TokenParser/Sandbox.php
CHANGED
@@ -24,9 +24,10 @@ class Twig_TokenParser_Sandbox extends Twig_TokenParser
|
|
24 |
{
|
25 |
public function parse(Twig_Token $token)
|
26 |
{
|
27 |
-
$this->parser->getStream()
|
|
|
28 |
$body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
|
29 |
-
$
|
30 |
|
31 |
// in a sandbox tag, only include tags are allowed
|
32 |
if (!$body instanceof Twig_Node_Include) {
|
@@ -36,7 +37,7 @@ class Twig_TokenParser_Sandbox extends Twig_TokenParser
|
|
36 |
}
|
37 |
|
38 |
if (!$node instanceof Twig_Node_Include) {
|
39 |
-
throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->
|
40 |
}
|
41 |
}
|
42 |
}
|
24 |
{
|
25 |
public function parse(Twig_Token $token)
|
26 |
{
|
27 |
+
$stream = $this->parser->getStream();
|
28 |
+
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
29 |
$body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
|
30 |
+
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
31 |
|
32 |
// in a sandbox tag, only include tags are allowed
|
33 |
if (!$body instanceof Twig_Node_Include) {
|
37 |
}
|
38 |
|
39 |
if (!$node instanceof Twig_Node_Include) {
|
40 |
+
throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext()->getName());
|
41 |
}
|
42 |
}
|
43 |
}
|
library/twig/twig/lib/Twig/TokenParser/Set.php
CHANGED
@@ -41,13 +41,13 @@ class Twig_TokenParser_Set extends Twig_TokenParser
|
|
41 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
42 |
|
43 |
if (count($names) !== count($values)) {
|
44 |
-
throw new Twig_Error_Syntax('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->
|
45 |
}
|
46 |
} else {
|
47 |
$capture = true;
|
48 |
|
49 |
if (count($names) > 1) {
|
50 |
-
throw new Twig_Error_Syntax('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->
|
51 |
}
|
52 |
|
53 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
41 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
42 |
|
43 |
if (count($names) !== count($values)) {
|
44 |
+
throw new Twig_Error_Syntax('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
45 |
}
|
46 |
} else {
|
47 |
$capture = true;
|
48 |
|
49 |
if (count($names) > 1) {
|
50 |
+
throw new Twig_Error_Syntax('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
51 |
}
|
52 |
|
53 |
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
library/twig/twig/lib/Twig/TokenParser/Use.php
CHANGED
@@ -31,7 +31,7 @@ class Twig_TokenParser_Use extends Twig_TokenParser
|
|
31 |
$stream = $this->parser->getStream();
|
32 |
|
33 |
if (!$template instanceof Twig_Node_Expression_Constant) {
|
34 |
-
throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->
|
35 |
}
|
36 |
|
37 |
$targets = array();
|
31 |
$stream = $this->parser->getStream();
|
32 |
|
33 |
if (!$template instanceof Twig_Node_Expression_Constant) {
|
34 |
+
throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName());
|
35 |
}
|
36 |
|
37 |
$targets = array();
|
library/twig/twig/lib/Twig/TokenParser/With.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 2016 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 |
+
* Creates a nested scope.
|
14 |
+
*
|
15 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
+
*/
|
17 |
+
class Twig_TokenParser_With extends Twig_TokenParser
|
18 |
+
{
|
19 |
+
public function parse(Twig_Token $token)
|
20 |
+
{
|
21 |
+
$stream = $this->parser->getStream();
|
22 |
+
|
23 |
+
$variables = null;
|
24 |
+
$only = false;
|
25 |
+
if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) {
|
26 |
+
$variables = $this->parser->getExpressionParser()->parseExpression();
|
27 |
+
$only = $stream->nextIf(Twig_Token::NAME_TYPE, 'only');
|
28 |
+
}
|
29 |
+
|
30 |
+
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
31 |
+
|
32 |
+
$body = $this->parser->subparse(array($this, 'decideWithEnd'), true);
|
33 |
+
|
34 |
+
$stream->expect(Twig_Token::BLOCK_END_TYPE);
|
35 |
+
|
36 |
+
return new Twig_Node_With($body, $variables, $only, $token->getLine(), $this->getTag());
|
37 |
+
}
|
38 |
+
|
39 |
+
public function decideWithEnd(Twig_Token $token)
|
40 |
+
{
|
41 |
+
return $token->test('endwith');
|
42 |
+
}
|
43 |
+
|
44 |
+
public function getTag()
|
45 |
+
{
|
46 |
+
return 'with';
|
47 |
+
}
|
48 |
+
}
|
library/twig/twig/lib/Twig/TokenParserBroker.php
CHANGED
@@ -24,8 +24,6 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
|
24 |
protected $brokers = array();
|
25 |
|
26 |
/**
|
27 |
-
* Constructor.
|
28 |
-
*
|
29 |
* @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances
|
30 |
* @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances
|
31 |
* @param bool $triggerDeprecationError
|
@@ -50,21 +48,11 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
|
50 |
}
|
51 |
}
|
52 |
|
53 |
-
/**
|
54 |
-
* Adds a TokenParser.
|
55 |
-
*
|
56 |
-
* @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
|
57 |
-
*/
|
58 |
public function addTokenParser(Twig_TokenParserInterface $parser)
|
59 |
{
|
60 |
$this->parsers[$parser->getTag()] = $parser;
|
61 |
}
|
62 |
|
63 |
-
/**
|
64 |
-
* Removes a TokenParser.
|
65 |
-
*
|
66 |
-
* @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
|
67 |
-
*/
|
68 |
public function removeTokenParser(Twig_TokenParserInterface $parser)
|
69 |
{
|
70 |
$name = $parser->getTag();
|
@@ -73,21 +61,11 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
|
|
73 |
}
|
74 |
}
|
75 |
|
76 |
-
/**
|
77 |
-
* Adds a TokenParserBroker.
|
78 |
-
*
|
79 |
-
* @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
|
80 |
-
*/
|
81 |
public function addTokenParserBroker(Twig_TokenParserBroker $broker)
|
82 |
{
|
83 |
$this->brokers[] = $broker;
|
84 |
}
|
85 |
|
86 |
-
/**
|
87 |
-
* Removes a TokenParserBroker.
|
88 |
-
*
|
89 |
-
* @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
|
90 |
-
*/
|
91 |
public function removeTokenParserBroker(Twig_TokenParserBroker $broker)
|
92 |
{
|
93 |
if (false !== $pos = array_search($broker, $this->brokers)) {
|
24 |
protected $brokers = array();
|
25 |
|
26 |
/**
|
|
|
|
|
27 |
* @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances
|
28 |
* @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances
|
29 |
* @param bool $triggerDeprecationError
|
48 |
}
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
51 |
public function addTokenParser(Twig_TokenParserInterface $parser)
|
52 |
{
|
53 |
$this->parsers[$parser->getTag()] = $parser;
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
|
|
56 |
public function removeTokenParser(Twig_TokenParserInterface $parser)
|
57 |
{
|
58 |
$name = $parser->getTag();
|
61 |
}
|
62 |
}
|
63 |
|
|
|
|
|
|
|
|
|
|
|
64 |
public function addTokenParserBroker(Twig_TokenParserBroker $broker)
|
65 |
{
|
66 |
$this->brokers[] = $broker;
|
67 |
}
|
68 |
|
|
|
|
|
|
|
|
|
|
|
69 |
public function removeTokenParserBroker(Twig_TokenParserBroker $broker)
|
70 |
{
|
71 |
if (false !== $pos = array_search($broker, $this->brokers)) {
|
library/twig/twig/lib/Twig/TokenParserBrokerInterface.php
CHANGED
@@ -26,14 +26,12 @@ interface Twig_TokenParserBrokerInterface
|
|
26 |
*
|
27 |
* @param string $tag A tag name
|
28 |
*
|
29 |
-
* @return null
|
30 |
*/
|
31 |
public function getTokenParser($tag);
|
32 |
|
33 |
/**
|
34 |
* Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of.
|
35 |
-
*
|
36 |
-
* @param Twig_ParserInterface $parser A Twig_ParserInterface interface
|
37 |
*/
|
38 |
public function setParser(Twig_ParserInterface $parser);
|
39 |
|
26 |
*
|
27 |
* @param string $tag A tag name
|
28 |
*
|
29 |
+
* @return Twig_TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found
|
30 |
*/
|
31 |
public function getTokenParser($tag);
|
32 |
|
33 |
/**
|
34 |
* Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of.
|
|
|
|
|
35 |
*/
|
36 |
public function setParser(Twig_ParserInterface $parser);
|
37 |
|
library/twig/twig/lib/Twig/TokenParserInterface.php
CHANGED
@@ -18,17 +18,13 @@ interface Twig_TokenParserInterface
|
|
18 |
{
|
19 |
/**
|
20 |
* Sets the parser associated with this token parser.
|
21 |
-
*
|
22 |
-
* @param Twig_Parser $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 |
-
* @
|
30 |
-
*
|
31 |
-
* @return Twig_NodeInterface A Twig_NodeInterface instance
|
32 |
*
|
33 |
* @throws Twig_Error_Syntax
|
34 |
*/
|
18 |
{
|
19 |
/**
|
20 |
* Sets the parser associated with this token parser.
|
|
|
|
|
21 |
*/
|
22 |
public function setParser(Twig_Parser $parser);
|
23 |
|
24 |
/**
|
25 |
* Parses a token and returns a node.
|
26 |
*
|
27 |
+
* @return Twig_NodeInterface
|
|
|
|
|
28 |
*
|
29 |
* @throws Twig_Error_Syntax
|
30 |
*/
|
library/twig/twig/lib/Twig/TokenStream.php
CHANGED
@@ -24,24 +24,27 @@ class Twig_TokenStream
|
|
24 |
private $source;
|
25 |
|
26 |
/**
|
27 |
-
*
|
28 |
-
*
|
29 |
-
* @param
|
30 |
-
* @param string $filename|null The name of the filename which tokens are associated with
|
31 |
-
* @param string $source|null The source code associated with the tokens
|
32 |
*/
|
33 |
-
public function __construct(array $tokens, $
|
34 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
$this->tokens = $tokens;
|
36 |
-
|
37 |
-
|
|
|
38 |
}
|
39 |
|
40 |
-
/**
|
41 |
-
* Returns a string representation of the token stream.
|
42 |
-
*
|
43 |
-
* @return string
|
44 |
-
*/
|
45 |
public function __toString()
|
46 |
{
|
47 |
return implode("\n", $this->tokens);
|
@@ -60,7 +63,7 @@ class Twig_TokenStream
|
|
60 |
public function next()
|
61 |
{
|
62 |
if (!isset($this->tokens[++$this->current])) {
|
63 |
-
throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->
|
64 |
}
|
65 |
|
66 |
return $this->tokens[$this->current - 1];
|
@@ -93,7 +96,7 @@ class Twig_TokenStream
|
|
93 |
Twig_Token::typeToEnglish($token->getType()), $token->getValue(),
|
94 |
Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''),
|
95 |
$line,
|
96 |
-
$this->
|
97 |
);
|
98 |
}
|
99 |
$this->next();
|
@@ -111,7 +114,7 @@ class Twig_TokenStream
|
|
111 |
public function look($number = 1)
|
112 |
{
|
113 |
if (!isset($this->tokens[$this->current + $number])) {
|
114 |
-
throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->
|
115 |
}
|
116 |
|
117 |
return $this->tokens[$this->current + $number];
|
@@ -138,8 +141,6 @@ class Twig_TokenStream
|
|
138 |
}
|
139 |
|
140 |
/**
|
141 |
-
* Gets the current token.
|
142 |
-
*
|
143 |
* @return Twig_Token
|
144 |
*/
|
145 |
public function getCurrent()
|
@@ -148,21 +149,43 @@ class Twig_TokenStream
|
|
148 |
}
|
149 |
|
150 |
/**
|
151 |
-
* Gets the
|
152 |
*
|
153 |
* @return string|null
|
|
|
|
|
154 |
*/
|
155 |
public function getFilename()
|
156 |
{
|
157 |
-
|
|
|
|
|
158 |
}
|
159 |
|
160 |
/**
|
161 |
* Gets the source code associated with this stream.
|
162 |
*
|
163 |
* @return string
|
|
|
|
|
|
|
|
|
164 |
*/
|
165 |
public function getSource()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
{
|
167 |
return $this->source;
|
168 |
}
|
24 |
private $source;
|
25 |
|
26 |
/**
|
27 |
+
* @param array $tokens An array of tokens
|
28 |
+
* @param string|null $name The name of the template which tokens are associated with
|
29 |
+
* @param string|null $source The source code associated with the tokens
|
|
|
|
|
30 |
*/
|
31 |
+
public function __construct(array $tokens, $name = null, $source = null)
|
32 |
{
|
33 |
+
if (!$name instanceof Twig_Source) {
|
34 |
+
if (null !== $name || null !== $source) {
|
35 |
+
@trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
|
36 |
+
}
|
37 |
+
$this->source = new Twig_Source($source, $name);
|
38 |
+
} else {
|
39 |
+
$this->source = $name;
|
40 |
+
}
|
41 |
+
|
42 |
$this->tokens = $tokens;
|
43 |
+
|
44 |
+
// deprecated, not used anymore, to be removed in 2.0
|
45 |
+
$this->filename = $this->source->getName();
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
|
|
48 |
public function __toString()
|
49 |
{
|
50 |
return implode("\n", $this->tokens);
|
63 |
public function next()
|
64 |
{
|
65 |
if (!isset($this->tokens[++$this->current])) {
|
66 |
+
throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source->getName());
|
67 |
}
|
68 |
|
69 |
return $this->tokens[$this->current - 1];
|
96 |
Twig_Token::typeToEnglish($token->getType()), $token->getValue(),
|
97 |
Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''),
|
98 |
$line,
|
99 |
+
$this->source->getName()
|
100 |
);
|
101 |
}
|
102 |
$this->next();
|
114 |
public function look($number = 1)
|
115 |
{
|
116 |
if (!isset($this->tokens[$this->current + $number])) {
|
117 |
+
throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source->getName());
|
118 |
}
|
119 |
|
120 |
return $this->tokens[$this->current + $number];
|
141 |
}
|
142 |
|
143 |
/**
|
|
|
|
|
144 |
* @return Twig_Token
|
145 |
*/
|
146 |
public function getCurrent()
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
+
* Gets the name associated with this stream (null if not defined).
|
153 |
*
|
154 |
* @return string|null
|
155 |
+
*
|
156 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
157 |
*/
|
158 |
public function getFilename()
|
159 |
{
|
160 |
+
@trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
|
161 |
+
|
162 |
+
return $this->source->getName();
|
163 |
}
|
164 |
|
165 |
/**
|
166 |
* Gets the source code associated with this stream.
|
167 |
*
|
168 |
* @return string
|
169 |
+
*
|
170 |
+
* @internal Don't use this as it might be empty depending on the environment configuration
|
171 |
+
*
|
172 |
+
* @deprecated since 1.27 (to be removed in 2.0)
|
173 |
*/
|
174 |
public function getSource()
|
175 |
+
{
|
176 |
+
@trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
|
177 |
+
|
178 |
+
return $this->source->getCode();
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Gets the source associated with this stream.
|
183 |
+
*
|
184 |
+
* @return Twig_Source
|
185 |
+
*
|
186 |
+
* @internal
|
187 |
+
*/
|
188 |
+
public function getSourceContext()
|
189 |
{
|
190 |
return $this->source;
|
191 |
}
|
library/twig/twig/lib/Twig/Util/DeprecationCollector.php
CHANGED
@@ -28,7 +28,7 @@ class Twig_Util_DeprecationCollector
|
|
28 |
* @param string $dir A directory where templates are stored
|
29 |
* @param string $ext Limit the loaded templates by extension
|
30 |
*
|
31 |
-
* @return array
|
32 |
*/
|
33 |
public function collectDir($dir, $ext = '.twig')
|
34 |
{
|
@@ -46,7 +46,7 @@ class Twig_Util_DeprecationCollector
|
|
46 |
*
|
47 |
* @param Iterator $iterator An iterator of templates (where keys are template names and values the contents of the template)
|
48 |
*
|
49 |
-
* @return array
|
50 |
*/
|
51 |
public function collect(Iterator $iterator)
|
52 |
{
|
28 |
* @param string $dir A directory where templates are stored
|
29 |
* @param string $ext Limit the loaded templates by extension
|
30 |
*
|
31 |
+
* @return array An array of deprecations
|
32 |
*/
|
33 |
public function collectDir($dir, $ext = '.twig')
|
34 |
{
|
46 |
*
|
47 |
* @param Iterator $iterator An iterator of templates (where keys are template names and values the contents of the template)
|
48 |
*
|
49 |
+
* @return array An array of deprecations
|
50 |
*/
|
51 |
public function collect(Iterator $iterator)
|
52 |
{
|
library/twig/twig/phpunit.xml.dist
CHANGED
@@ -17,6 +17,14 @@
|
|
17 |
</testsuite>
|
18 |
</testsuites>
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
<filter>
|
21 |
<whitelist>
|
22 |
<directory suffix=".php">./lib/Twig/</directory>
|
17 |
</testsuite>
|
18 |
</testsuites>
|
19 |
|
20 |
+
<php>
|
21 |
+
<ini name="error_reporting" value="-1" />
|
22 |
+
</php>
|
23 |
+
|
24 |
+
<listeners>
|
25 |
+
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
|
26 |
+
</listeners>
|
27 |
+
|
28 |
<filter>
|
29 |
<whitelist>
|
30 |
<directory suffix=".php">./lib/Twig/</directory>
|
library/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php
CHANGED
@@ -115,7 +115,7 @@ class Twig_Tests_Cache_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
115 |
// Create root directory.
|
116 |
@mkdir($this->directory, 0777, true);
|
117 |
// Create read-only subdirectory.
|
118 |
-
@mkdir($this->directory.'/cache'
|
119 |
$this->assertTrue(is_dir($this->directory.'/cache'));
|
120 |
|
121 |
$this->cache->write($key, $content);
|
115 |
// Create root directory.
|
116 |
@mkdir($this->directory, 0777, true);
|
117 |
// Create read-only subdirectory.
|
118 |
+
@mkdir($this->directory.'/cache', 0555);
|
119 |
$this->assertTrue(is_dir($this->directory.'/cache'));
|
120 |
|
121 |
$this->cache->write($key, $content);
|
library/twig/twig/test/Twig/Tests/EnvironmentTest.php
CHANGED
@@ -15,6 +15,27 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
15 |
{
|
16 |
private $deprecations = array();
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* @expectedException LogicException
|
20 |
* @expectedExceptionMessage You must set a loader first.
|
@@ -43,16 +64,21 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
43 |
$this->assertEquals('foo\x3Cbr\x2F\x20\x3E foo\x3Cbr\x2F\x20\x3E', $twig->render('js', array('bar' => 'foo<br/ >')));
|
44 |
}
|
45 |
|
46 |
-
public function escapingStrategyCallback($
|
47 |
{
|
48 |
-
return $
|
49 |
}
|
50 |
|
51 |
public function testGlobals()
|
52 |
{
|
|
|
|
|
|
|
|
|
|
|
53 |
// globals can be added after calling getGlobals
|
54 |
|
55 |
-
$twig = new Twig_Environment($
|
56 |
$twig->addGlobal('foo', 'foo');
|
57 |
$twig->getGlobals();
|
58 |
$twig->addGlobal('foo', 'bar');
|
@@ -60,7 +86,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
60 |
$this->assertEquals('bar', $globals['foo']);
|
61 |
|
62 |
// globals can be modified after a template has been loaded
|
63 |
-
$twig = new Twig_Environment($
|
64 |
$twig->addGlobal('foo', 'foo');
|
65 |
$twig->getGlobals();
|
66 |
$twig->loadTemplate('index');
|
@@ -69,7 +95,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
69 |
$this->assertEquals('bar', $globals['foo']);
|
70 |
|
71 |
// globals can be modified after extensions init
|
72 |
-
$twig = new Twig_Environment($
|
73 |
$twig->addGlobal('foo', 'foo');
|
74 |
$twig->getGlobals();
|
75 |
$twig->getFunctions();
|
@@ -78,7 +104,8 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
78 |
$this->assertEquals('bar', $globals['foo']);
|
79 |
|
80 |
// globals can be modified after extensions and a template has been loaded
|
81 |
-
$
|
|
|
82 |
$twig->addGlobal('foo', 'foo');
|
83 |
$twig->getGlobals();
|
84 |
$twig->getFunctions();
|
@@ -87,7 +114,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
87 |
$globals = $twig->getGlobals();
|
88 |
$this->assertEquals('bar', $globals['foo']);
|
89 |
|
90 |
-
$twig = new Twig_Environment($
|
91 |
$twig->getGlobals();
|
92 |
$twig->addGlobal('foo', 'bar');
|
93 |
$template = $twig->loadTemplate('index');
|
@@ -95,7 +122,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
95 |
|
96 |
/* to be uncomment in Twig 2.0
|
97 |
// globals cannot be added after a template has been loaded
|
98 |
-
$twig = new Twig_Environment($
|
99 |
$twig->addGlobal('foo', 'foo');
|
100 |
$twig->getGlobals();
|
101 |
$twig->loadTemplate('index');
|
@@ -107,7 +134,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
107 |
}
|
108 |
|
109 |
// globals cannot be added after extensions init
|
110 |
-
$twig = new Twig_Environment($
|
111 |
$twig->addGlobal('foo', 'foo');
|
112 |
$twig->getGlobals();
|
113 |
$twig->getFunctions();
|
@@ -119,7 +146,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
119 |
}
|
120 |
|
121 |
// globals cannot be added after extensions and a template has been loaded
|
122 |
-
$twig = new Twig_Environment($
|
123 |
$twig->addGlobal('foo', 'foo');
|
124 |
$twig->getGlobals();
|
125 |
$twig->getFunctions();
|
@@ -132,7 +159,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
132 |
}
|
133 |
|
134 |
// test adding globals after a template has been loaded without call to getGlobals
|
135 |
-
$twig = new Twig_Environment($
|
136 |
$twig->loadTemplate('index');
|
137 |
try {
|
138 |
$twig->addGlobal('bar', 'bar');
|
@@ -152,7 +179,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
152 |
$twig = new Twig_Environment($loader = new Twig_Loader_Array(array('index' => '{{ foo }}')), $options);
|
153 |
|
154 |
$key = $cache->generateKey('index', $twig->getTemplateClass('index'));
|
155 |
-
$cache->write($key, $twig->compileSource('{{ foo }}', 'index'));
|
156 |
|
157 |
// check that extensions won't be initialized when rendering a template that is already in the cache
|
158 |
$twig = $this
|
@@ -190,7 +217,9 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
190 |
->will($this->returnValue(0));
|
191 |
$loader->expects($this->never())
|
192 |
->method('isFresh');
|
193 |
-
$cache->expects($this->
|
|
|
|
|
194 |
->method('load');
|
195 |
|
196 |
$twig->loadTemplate($templateName);
|
@@ -218,7 +247,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
218 |
$loader->expects($this->once())
|
219 |
->method('isFresh')
|
220 |
->will($this->returnValue(true));
|
221 |
-
$cache->expects($this->
|
222 |
->method('load');
|
223 |
|
224 |
$twig->loadTemplate($templateName);
|
@@ -244,12 +273,46 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
244 |
$loader->expects($this->once())
|
245 |
->method('isFresh')
|
246 |
->will($this->returnValue(false));
|
247 |
-
$cache->expects($this->
|
|
|
|
|
248 |
->method('load');
|
249 |
|
250 |
$twig->loadTemplate($templateName);
|
251 |
}
|
252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
public function testAddExtension()
|
254 |
{
|
255 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
@@ -286,7 +349,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
286 |
$this->assertArrayHasKey('foo_global', $twig->getGlobals());
|
287 |
|
288 |
$this->assertCount(1, $this->deprecations);
|
289 |
-
$this->assertContains('Defining the getGlobals() method in the "
|
290 |
|
291 |
restore_error_handler();
|
292 |
}
|
@@ -297,7 +360,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
297 |
public function testRemoveExtension()
|
298 |
{
|
299 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
300 |
-
$twig->addExtension(new
|
301 |
$twig->removeExtension('environment_test');
|
302 |
|
303 |
$this->assertFalse(array_key_exists('test', $twig->getTags()));
|
@@ -312,17 +375,22 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
312 |
|
313 |
public function testAddMockExtension()
|
314 |
{
|
315 |
-
|
316 |
-
$extension
|
317 |
-
|
318 |
-
|
|
|
|
|
|
|
|
|
|
|
319 |
|
320 |
$loader = new Twig_Loader_Array(array('page' => 'hey'));
|
321 |
|
322 |
$twig = new Twig_Environment($loader);
|
323 |
$twig->addExtension($extension);
|
324 |
|
325 |
-
$this->assertInstanceOf('Twig_ExtensionInterface', $twig->getExtension(
|
326 |
$this->assertTrue($twig->isTemplateFresh('page', time()));
|
327 |
}
|
328 |
|
@@ -348,7 +416,7 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
348 |
$twig->initRuntime();
|
349 |
|
350 |
$this->assertCount(1, $this->deprecations);
|
351 |
-
$this->assertContains('Defining the initRuntime() method in the "
|
352 |
|
353 |
restore_error_handler();
|
354 |
}
|
@@ -371,8 +439,8 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
371 |
$this->deprecations = array();
|
372 |
set_error_handler(array($this, 'handleError'));
|
373 |
|
374 |
-
$twig->addExtension(new
|
375 |
-
$twig->addExtension(new
|
376 |
|
377 |
$this->assertCount(1, $this->deprecations);
|
378 |
$this->assertContains('The possibility to register the same extension twice', $this->deprecations[0]);
|
@@ -380,13 +448,41 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
|
|
380 |
restore_error_handler();
|
381 |
}
|
382 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
protected function getMockLoader($templateName, $templateContent)
|
384 |
{
|
385 |
-
|
|
|
|
|
386 |
$loader->expects($this->any())
|
387 |
-
->method('
|
388 |
->with($templateName)
|
389 |
-
->will($this->returnValue($templateContent));
|
390 |
$loader->expects($this->any())
|
391 |
->method('getCacheKey')
|
392 |
->with($templateName)
|
@@ -404,11 +500,6 @@ class Twig_Tests_EnvironmentTest_Extension_WithGlobals extends Twig_Extension
|
|
404 |
'foo_global' => 'foo_global',
|
405 |
);
|
406 |
}
|
407 |
-
|
408 |
-
public function getName()
|
409 |
-
{
|
410 |
-
return 'environment_test';
|
411 |
-
}
|
412 |
}
|
413 |
|
414 |
class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension implements Twig_Extension_GlobalsInterface
|
@@ -462,13 +553,31 @@ class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension implements Twi
|
|
462 |
'foo_global' => 'foo_global',
|
463 |
);
|
464 |
}
|
|
|
465 |
|
|
|
|
|
466 |
public function getName()
|
467 |
{
|
468 |
return 'environment_test';
|
469 |
}
|
470 |
}
|
471 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser
|
473 |
{
|
474 |
public function parse(Twig_Token $token)
|
@@ -504,21 +613,40 @@ class Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime extends Twi
|
|
504 |
public function initRuntime(Twig_Environment $env)
|
505 |
{
|
506 |
}
|
|
|
507 |
|
508 |
-
|
|
|
|
|
509 |
{
|
510 |
-
return 'with_deprecation';
|
511 |
}
|
512 |
}
|
513 |
|
514 |
-
class
|
515 |
{
|
516 |
-
public function
|
517 |
{
|
|
|
|
|
|
|
|
|
518 |
}
|
519 |
|
520 |
public function getName()
|
521 |
{
|
522 |
-
return '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
523 |
}
|
524 |
}
|
|
|
|
|
|
|
|
|
|
15 |
{
|
16 |
private $deprecations = array();
|
17 |
|
18 |
+
/**
|
19 |
+
* @group legacy
|
20 |
+
*/
|
21 |
+
public function testLegacyTokenizeSignature()
|
22 |
+
{
|
23 |
+
$env = new Twig_Environment();
|
24 |
+
$stream = $env->tokenize('{{ foo }}', 'foo');
|
25 |
+
$this->assertEquals('{{ foo }}', $stream->getSource());
|
26 |
+
$this->assertEquals('foo', $stream->getFilename());
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @group legacy
|
31 |
+
*/
|
32 |
+
public function testLegacyCompileSourceSignature()
|
33 |
+
{
|
34 |
+
$loader = new Twig_Loader_Array(array('foo' => '{{ foo }}'));
|
35 |
+
$env = new Twig_Environment($loader);
|
36 |
+
$this->assertContains('getTemplateName', $env->compileSource('{{ foo }}', 'foo'));
|
37 |
+
}
|
38 |
+
|
39 |
/**
|
40 |
* @expectedException LogicException
|
41 |
* @expectedExceptionMessage You must set a loader first.
|
64 |
$this->assertEquals('foo\x3Cbr\x2F\x20\x3E foo\x3Cbr\x2F\x20\x3E', $twig->render('js', array('bar' => 'foo<br/ >')));
|
65 |
}
|
66 |
|
67 |
+
public function escapingStrategyCallback($name)
|
68 |
{
|
69 |
+
return $name;
|
70 |
}
|
71 |
|
72 |
public function testGlobals()
|
73 |
{
|
74 |
+
// to be removed in 2.0
|
75 |
+
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
|
76 |
+
//$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
|
77 |
+
$loader->expects($this->any())->method('getSourceContext')->will($this->returnValue(new Twig_Source('', '')));
|
78 |
+
|
79 |
// globals can be added after calling getGlobals
|
80 |
|
81 |
+
$twig = new Twig_Environment($loader);
|
82 |
$twig->addGlobal('foo', 'foo');
|
83 |
$twig->getGlobals();
|
84 |
$twig->addGlobal('foo', 'bar');
|
86 |
$this->assertEquals('bar', $globals['foo']);
|
87 |
|
88 |
// globals can be modified after a template has been loaded
|
89 |
+
$twig = new Twig_Environment($loader);
|
90 |
$twig->addGlobal('foo', 'foo');
|
91 |
$twig->getGlobals();
|
92 |
$twig->loadTemplate('index');
|
95 |
$this->assertEquals('bar', $globals['foo']);
|
96 |
|
97 |
// globals can be modified after extensions init
|
98 |
+
$twig = new Twig_Environment($loader);
|
99 |
$twig->addGlobal('foo', 'foo');
|
100 |
$twig->getGlobals();
|
101 |
$twig->getFunctions();
|
104 |
$this->assertEquals('bar', $globals['foo']);
|
105 |
|
106 |
// globals can be modified after extensions and a template has been loaded
|
107 |
+
$arrayLoader = new Twig_Loader_Array(array('index' => '{{foo}}'));
|
108 |
+
$twig = new Twig_Environment($arrayLoader);
|
109 |
$twig->addGlobal('foo', 'foo');
|
110 |
$twig->getGlobals();
|
111 |
$twig->getFunctions();
|
114 |
$globals = $twig->getGlobals();
|
115 |
$this->assertEquals('bar', $globals['foo']);
|
116 |
|
117 |
+
$twig = new Twig_Environment($arrayLoader);
|
118 |
$twig->getGlobals();
|
119 |
$twig->addGlobal('foo', 'bar');
|
120 |
$template = $twig->loadTemplate('index');
|
122 |
|
123 |
/* to be uncomment in Twig 2.0
|
124 |
// globals cannot be added after a template has been loaded
|
125 |
+
$twig = new Twig_Environment($loader);
|
126 |
$twig->addGlobal('foo', 'foo');
|
127 |
$twig->getGlobals();
|
128 |
$twig->loadTemplate('index');
|
134 |
}
|
135 |
|
136 |
// globals cannot be added after extensions init
|
137 |
+
$twig = new Twig_Environment($loader);
|
138 |
$twig->addGlobal('foo', 'foo');
|
139 |
$twig->getGlobals();
|
140 |
$twig->getFunctions();
|
146 |
}
|
147 |
|
148 |
// globals cannot be added after extensions and a template has been loaded
|
149 |
+
$twig = new Twig_Environment($loader);
|
150 |
$twig->addGlobal('foo', 'foo');
|
151 |
$twig->getGlobals();
|
152 |
$twig->getFunctions();
|
159 |
}
|
160 |
|
161 |
// test adding globals after a template has been loaded without call to getGlobals
|
162 |
+
$twig = new Twig_Environment($loader);
|
163 |
$twig->loadTemplate('index');
|
164 |
try {
|
165 |
$twig->addGlobal('bar', 'bar');
|
179 |
$twig = new Twig_Environment($loader = new Twig_Loader_Array(array('index' => '{{ foo }}')), $options);
|
180 |
|
181 |
$key = $cache->generateKey('index', $twig->getTemplateClass('index'));
|
182 |
+
$cache->write($key, $twig->compileSource(new Twig_Source('{{ foo }}', 'index')));
|
183 |
|
184 |
// check that extensions won't be initialized when rendering a template that is already in the cache
|
185 |
$twig = $this
|
217 |
->will($this->returnValue(0));
|
218 |
$loader->expects($this->never())
|
219 |
->method('isFresh');
|
220 |
+
$cache->expects($this->once())
|
221 |
+
->method('write');
|
222 |
+
$cache->expects($this->once())
|
223 |
->method('load');
|
224 |
|
225 |
$twig->loadTemplate($templateName);
|
247 |
$loader->expects($this->once())
|
248 |
->method('isFresh')
|
249 |
->will($this->returnValue(true));
|
250 |
+
$cache->expects($this->atLeastOnce())
|
251 |
->method('load');
|
252 |
|
253 |
$twig->loadTemplate($templateName);
|
273 |
$loader->expects($this->once())
|
274 |
->method('isFresh')
|
275 |
->will($this->returnValue(false));
|
276 |
+
$cache->expects($this->once())
|
277 |
+
->method('write');
|
278 |
+
$cache->expects($this->once())
|
279 |
->method('load');
|
280 |
|
281 |
$twig->loadTemplate($templateName);
|
282 |
}
|
283 |
|
284 |
+
/**
|
285 |
+
* @group legacy
|
286 |
+
*/
|
287 |
+
public function testHasGetExtensionWithDynamicName()
|
288 |
+
{
|
289 |
+
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
290 |
+
|
291 |
+
$ext1 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1');
|
292 |
+
$ext2 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2');
|
293 |
+
$twig->addExtension($ext1);
|
294 |
+
$twig->addExtension($ext2);
|
295 |
+
|
296 |
+
$this->assertTrue($twig->hasExtension('ext1'));
|
297 |
+
$this->assertTrue($twig->hasExtension('ext2'));
|
298 |
+
|
299 |
+
$this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName'));
|
300 |
+
|
301 |
+
$this->assertSame($ext1, $twig->getExtension('ext1'));
|
302 |
+
$this->assertSame($ext2, $twig->getExtension('ext2'));
|
303 |
+
}
|
304 |
+
|
305 |
+
public function testHasGetExtensionByClassName()
|
306 |
+
{
|
307 |
+
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
308 |
+
$twig->addExtension($ext = new Twig_Tests_EnvironmentTest_Extension());
|
309 |
+
$this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension'));
|
310 |
+
$this->assertTrue($twig->hasExtension('\Twig_Tests_EnvironmentTest_Extension'));
|
311 |
+
|
312 |
+
$this->assertSame($ext, $twig->getExtension('Twig_Tests_EnvironmentTest_Extension'));
|
313 |
+
$this->assertSame($ext, $twig->getExtension('\Twig_Tests_EnvironmentTest_Extension'));
|
314 |
+
}
|
315 |
+
|
316 |
public function testAddExtension()
|
317 |
{
|
318 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
349 |
$this->assertArrayHasKey('foo_global', $twig->getGlobals());
|
350 |
|
351 |
$this->assertCount(1, $this->deprecations);
|
352 |
+
$this->assertContains('Defining the getGlobals() method in the "Twig_Tests_EnvironmentTest_Extension_WithGlobals" extension ', $this->deprecations[0]);
|
353 |
|
354 |
restore_error_handler();
|
355 |
}
|
360 |
public function testRemoveExtension()
|
361 |
{
|
362 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
363 |
+
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName());
|
364 |
$twig->removeExtension('environment_test');
|
365 |
|
366 |
$this->assertFalse(array_key_exists('test', $twig->getTags()));
|
375 |
|
376 |
public function testAddMockExtension()
|
377 |
{
|
378 |
+
// should be replaced by the following in 2.0 (this current code is just to avoid a dep notice)
|
379 |
+
// $extension = $this->getMockBuilder('Twig_Extension')->getMock();
|
380 |
+
$extension = eval(<<<EOF
|
381 |
+
class Twig_Tests_EnvironmentTest_ExtensionInEval extends Twig_Extension
|
382 |
+
{
|
383 |
+
}
|
384 |
+
EOF
|
385 |
+
);
|
386 |
+
$extension = new Twig_Tests_EnvironmentTest_ExtensionInEval();
|
387 |
|
388 |
$loader = new Twig_Loader_Array(array('page' => 'hey'));
|
389 |
|
390 |
$twig = new Twig_Environment($loader);
|
391 |
$twig->addExtension($extension);
|
392 |
|
393 |
+
$this->assertInstanceOf('Twig_ExtensionInterface', $twig->getExtension(get_class($extension)));
|
394 |
$this->assertTrue($twig->isTemplateFresh('page', time()));
|
395 |
}
|
396 |
|
416 |
$twig->initRuntime();
|
417 |
|
418 |
$this->assertCount(1, $this->deprecations);
|
419 |
+
$this->assertContains('Defining the initRuntime() method in the "Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime" extension is deprecated since version 1.23.', $this->deprecations[0]);
|
420 |
|
421 |
restore_error_handler();
|
422 |
}
|
439 |
$this->deprecations = array();
|
440 |
set_error_handler(array($this, 'handleError'));
|
441 |
|
442 |
+
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName());
|
443 |
+
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName());
|
444 |
|
445 |
$this->assertCount(1, $this->deprecations);
|
446 |
$this->assertContains('The possibility to register the same extension twice', $this->deprecations[0]);
|
448 |
restore_error_handler();
|
449 |
}
|
450 |
|
451 |
+
public function testAddRuntimeLoader()
|
452 |
+
{
|
453 |
+
$runtimeLoader = $this->getMockBuilder('Twig_RuntimeLoaderInterface')->getMock();
|
454 |
+
$runtimeLoader->expects($this->any())->method('load')->will($this->returnValue(new Twig_Tests_EnvironmentTest_Runtime()));
|
455 |
+
|
456 |
+
$loader = new Twig_Loader_Array(array(
|
457 |
+
'func_array' => '{{ from_runtime_array("foo") }}',
|
458 |
+
'func_array_default' => '{{ from_runtime_array() }}',
|
459 |
+
'func_array_named_args' => '{{ from_runtime_array(name="foo") }}',
|
460 |
+
'func_string' => '{{ from_runtime_string("foo") }}',
|
461 |
+
'func_string_default' => '{{ from_runtime_string() }}',
|
462 |
+
'func_string_named_args' => '{{ from_runtime_string(name="foo") }}',
|
463 |
+
));
|
464 |
+
|
465 |
+
$twig = new Twig_Environment($loader);
|
466 |
+
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime());
|
467 |
+
$twig->addRuntimeLoader($runtimeLoader);
|
468 |
+
|
469 |
+
$this->assertEquals('foo', $twig->render('func_array'));
|
470 |
+
$this->assertEquals('bar', $twig->render('func_array_default'));
|
471 |
+
$this->assertEquals('foo', $twig->render('func_array_named_args'));
|
472 |
+
$this->assertEquals('foo', $twig->render('func_string'));
|
473 |
+
$this->assertEquals('bar', $twig->render('func_string_default'));
|
474 |
+
$this->assertEquals('foo', $twig->render('func_string_named_args'));
|
475 |
+
}
|
476 |
+
|
477 |
protected function getMockLoader($templateName, $templateContent)
|
478 |
{
|
479 |
+
// to be removed in 2.0
|
480 |
+
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
|
481 |
+
//$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
|
482 |
$loader->expects($this->any())
|
483 |
+
->method('getSourceContext')
|
484 |
->with($templateName)
|
485 |
+
->will($this->returnValue(new Twig_Source($templateContent, $templateName)));
|
486 |
$loader->expects($this->any())
|
487 |
->method('getCacheKey')
|
488 |
->with($templateName)
|
500 |
'foo_global' => 'foo_global',
|
501 |
);
|
502 |
}
|
|
|
|
|
|
|
|
|
|
|
503 |
}
|
504 |
|
505 |
class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension implements Twig_Extension_GlobalsInterface
|
553 |
'foo_global' => 'foo_global',
|
554 |
);
|
555 |
}
|
556 |
+
}
|
557 |
|
558 |
+
class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends Twig_Extension
|
559 |
+
{
|
560 |
public function getName()
|
561 |
{
|
562 |
return 'environment_test';
|
563 |
}
|
564 |
}
|
565 |
|
566 |
+
class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends Twig_Extension
|
567 |
+
{
|
568 |
+
private $name;
|
569 |
+
|
570 |
+
public function __construct($name)
|
571 |
+
{
|
572 |
+
$this->name = $name;
|
573 |
+
}
|
574 |
+
|
575 |
+
public function getName()
|
576 |
+
{
|
577 |
+
return $this->name;
|
578 |
+
}
|
579 |
+
}
|
580 |
+
|
581 |
class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser
|
582 |
{
|
583 |
public function parse(Twig_Token $token)
|
613 |
public function initRuntime(Twig_Environment $env)
|
614 |
{
|
615 |
}
|
616 |
+
}
|
617 |
|
618 |
+
class Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime extends Twig_Extension implements Twig_Extension_InitRuntimeInterface
|
619 |
+
{
|
620 |
+
public function initRuntime(Twig_Environment $env)
|
621 |
{
|
|
|
622 |
}
|
623 |
}
|
624 |
|
625 |
+
class Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime extends Twig_Extension
|
626 |
{
|
627 |
+
public function getFunctions()
|
628 |
{
|
629 |
+
return array(
|
630 |
+
new Twig_SimpleFunction('from_runtime_array', array('Twig_Tests_EnvironmentTest_Runtime', 'fromRuntime')),
|
631 |
+
new Twig_SimpleFunction('from_runtime_string', 'Twig_Tests_EnvironmentTest_Runtime::fromRuntime'),
|
632 |
+
);
|
633 |
}
|
634 |
|
635 |
public function getName()
|
636 |
{
|
637 |
+
return 'from_runtime';
|
638 |
+
}
|
639 |
+
}
|
640 |
+
|
641 |
+
class Twig_Tests_EnvironmentTest_Runtime
|
642 |
+
{
|
643 |
+
public function fromRuntime($name = 'bar')
|
644 |
+
{
|
645 |
+
return $name;
|
646 |
}
|
647 |
}
|
648 |
+
|
649 |
+
// to be removed in 2.0
|
650 |
+
interface Twig_EnvironmentTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
|
651 |
+
{
|
652 |
+
}
|
library/twig/twig/test/Twig/Tests/ErrorTest.php
CHANGED
@@ -14,7 +14,7 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
14 |
public function testErrorWithObjectFilename()
|
15 |
{
|
16 |
$error = new Twig_Error('foo');
|
17 |
-
$error->
|
18 |
|
19 |
$this->assertContains('test'.DIRECTORY_SEPARATOR.'Twig'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage());
|
20 |
}
|
@@ -22,7 +22,7 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
22 |
public function testErrorWithArrayFilename()
|
23 |
{
|
24 |
$error = new Twig_Error('foo');
|
25 |
-
$error->
|
26 |
|
27 |
$this->assertEquals('foo in {"foo":"bar"}', $error->getMessage());
|
28 |
}
|
@@ -38,9 +38,9 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
38 |
|
39 |
$this->fail();
|
40 |
} catch (Twig_Error_Runtime $e) {
|
41 |
-
$this->assertEquals('Variable "foo" does not exist in "index.html" at line 3', $e->getMessage());
|
42 |
$this->assertEquals(3, $e->getTemplateLine());
|
43 |
-
$this->assertEquals('index.html', $e->
|
44 |
}
|
45 |
|
46 |
try {
|
@@ -50,7 +50,7 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
50 |
} catch (Twig_Error_Runtime $e) {
|
51 |
$this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index.html" at line 3.', $e->getMessage());
|
52 |
$this->assertEquals(3, $e->getTemplateLine());
|
53 |
-
$this->assertEquals('index.html', $e->
|
54 |
}
|
55 |
}
|
56 |
|
@@ -69,9 +69,9 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
69 |
|
70 |
$this->fail();
|
71 |
} catch (Twig_Error_Runtime $e) {
|
72 |
-
$this->assertEquals(sprintf('Variable "foo" does not exist in "%s" at line %d', $name, $line), $e->getMessage());
|
73 |
$this->assertEquals($line, $e->getTemplateLine());
|
74 |
-
$this->assertEquals($name, $e->
|
75 |
}
|
76 |
|
77 |
try {
|
@@ -81,7 +81,7 @@ class Twig_Tests_ErrorTest extends PHPUnit_Framework_TestCase
|
|
81 |
} catch (Twig_Error_Runtime $e) {
|
82 |
$this->assertEquals(sprintf('An exception has been thrown during the rendering of a template ("Runtime error...") in "%s" at line %d.', $name, $line), $e->getMessage());
|
83 |
$this->assertEquals($line, $e->getTemplateLine());
|
84 |
-
$this->assertEquals($name, $e->
|
85 |
}
|
86 |
}
|
87 |
|
14 |
public function testErrorWithObjectFilename()
|
15 |
{
|
16 |
$error = new Twig_Error('foo');
|
17 |
+
$error->setTemplateName(new SplFileInfo(__FILE__));
|
18 |
|
19 |
$this->assertContains('test'.DIRECTORY_SEPARATOR.'Twig'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage());
|
20 |
}
|
22 |
public function testErrorWithArrayFilename()
|
23 |
{
|
24 |
$error = new Twig_Error('foo');
|
25 |
+
$error->setTemplateName(array('foo' => 'bar'));
|
26 |
|
27 |
$this->assertEquals('foo in {"foo":"bar"}', $error->getMessage());
|
28 |
}
|
38 |
|
39 |
$this->fail();
|
40 |
} catch (Twig_Error_Runtime $e) {
|
41 |
+
$this->assertEquals('Variable "foo" does not exist in "index.html" at line 3.', $e->getMessage());
|
42 |
$this->assertEquals(3, $e->getTemplateLine());
|
43 |
+
$this->assertEquals('index.html', $e->getTemplateName());
|
44 |
}
|
45 |
|
46 |
try {
|
50 |
} catch (Twig_Error_Runtime $e) {
|
51 |
$this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index.html" at line 3.', $e->getMessage());
|
52 |
$this->assertEquals(3, $e->getTemplateLine());
|
53 |
+
$this->assertEquals('index.html', $e->getTemplateName());
|
54 |
}
|
55 |
}
|
56 |
|
69 |
|
70 |
$this->fail();
|
71 |
} catch (Twig_Error_Runtime $e) {
|
72 |
+
$this->assertEquals(sprintf('Variable "foo" does not exist in "%s" at line %d.', $name, $line), $e->getMessage());
|
73 |
$this->assertEquals($line, $e->getTemplateLine());
|
74 |
+
$this->assertEquals($name, $e->getTemplateName());
|
75 |
}
|
76 |
|
77 |
try {
|
81 |
} catch (Twig_Error_Runtime $e) {
|
82 |
$this->assertEquals(sprintf('An exception has been thrown during the rendering of a template ("Runtime error...") in "%s" at line %d.', $name, $line), $e->getMessage());
|
83 |
$this->assertEquals($line, $e->getTemplateLine());
|
84 |
+
$this->assertEquals($name, $e->getTemplateName());
|
85 |
}
|
86 |
}
|
87 |
|
library/twig/twig/test/Twig/Tests/ExpressionParserTest.php
CHANGED
@@ -20,7 +20,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
20 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
21 |
$parser = new Twig_Parser($env);
|
22 |
|
23 |
-
$parser->parse($env->tokenize($template, 'index'));
|
24 |
}
|
25 |
|
26 |
public function getFailingTestsForAssignment()
|
@@ -47,7 +47,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
47 |
public function testArrayExpression($template, $expected)
|
48 |
{
|
49 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
50 |
-
$stream = $env->tokenize($template, '
|
51 |
$parser = new Twig_Parser($env);
|
52 |
|
53 |
$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr'));
|
@@ -62,7 +62,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
62 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
63 |
$parser = new Twig_Parser($env);
|
64 |
|
65 |
-
$parser->parse($env->tokenize($template, 'index'));
|
66 |
}
|
67 |
|
68 |
public function getFailingTestsForArray()
|
@@ -155,7 +155,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
155 |
public function testStringExpressionDoesNotConcatenateTwoConsecutiveStrings()
|
156 |
{
|
157 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
|
158 |
-
$stream = $env->tokenize('{{ "a" "b" }}', 'index');
|
159 |
$parser = new Twig_Parser($env);
|
160 |
|
161 |
$parser->parse($stream);
|
@@ -167,7 +167,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
167 |
public function testStringExpression($template, $expected)
|
168 |
{
|
169 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
|
170 |
-
$stream = $env->tokenize($template, '
|
171 |
$parser = new Twig_Parser($env);
|
172 |
|
173 |
$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr'));
|
@@ -228,7 +228,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
228 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
229 |
$parser = new Twig_Parser($env);
|
230 |
|
231 |
-
$parser->parse($env->tokenize('{{ foo.bar(name="Foo") }}', 'index'));
|
232 |
}
|
233 |
|
234 |
/**
|
@@ -239,7 +239,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
239 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
240 |
$parser = new Twig_Parser($env);
|
241 |
|
242 |
-
$parser->parse($env->tokenize('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index'));
|
243 |
}
|
244 |
|
245 |
/**
|
@@ -251,7 +251,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
251 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
252 |
$parser = new Twig_Parser($env);
|
253 |
|
254 |
-
$parser->parse($env->tokenize('{% macro foo("a") %}{% endmacro %}', 'index'));
|
255 |
}
|
256 |
|
257 |
/**
|
@@ -264,7 +264,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
264 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
265 |
$parser = new Twig_Parser($env);
|
266 |
|
267 |
-
$parser->parse($env->tokenize($template, 'index'));
|
268 |
}
|
269 |
|
270 |
public function getMacroDefinitionDoesNotSupportNonConstantDefaultValues()
|
@@ -283,7 +283,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
283 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
284 |
$parser = new Twig_Parser($env);
|
285 |
|
286 |
-
$parser->parse($env->tokenize($template, 'index'));
|
287 |
}
|
288 |
|
289 |
public function getMacroDefinitionSupportsConstantDefaultValues()
|
@@ -308,7 +308,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
308 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
309 |
$parser = new Twig_Parser($env);
|
310 |
|
311 |
-
$parser->parse($env->tokenize('{{ cycl() }}', 'index'));
|
312 |
}
|
313 |
|
314 |
/**
|
@@ -320,7 +320,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
320 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
321 |
$parser = new Twig_Parser($env);
|
322 |
|
323 |
-
$parser->parse($env->tokenize('{{ foobar() }}', 'index'));
|
324 |
}
|
325 |
|
326 |
/**
|
@@ -332,7 +332,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
332 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
333 |
$parser = new Twig_Parser($env);
|
334 |
|
335 |
-
$parser->parse($env->tokenize('{{ 1|lowe }}', 'index'));
|
336 |
}
|
337 |
|
338 |
/**
|
@@ -344,7 +344,7 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
344 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
345 |
$parser = new Twig_Parser($env);
|
346 |
|
347 |
-
$parser->parse($env->tokenize('{{ 1|foobar }}', 'index'));
|
348 |
}
|
349 |
|
350 |
/**
|
@@ -355,8 +355,8 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
355 |
{
|
356 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
357 |
$parser = new Twig_Parser($env);
|
358 |
-
|
359 |
-
$parser->parse($
|
360 |
}
|
361 |
|
362 |
/**
|
@@ -368,6 +368,6 @@ class Twig_Tests_ExpressionParserTest extends PHPUnit_Framework_TestCase
|
|
368 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
369 |
$parser = new Twig_Parser($env);
|
370 |
|
371 |
-
$parser->parse($env->tokenize('{{ 1 is foobar }}', 'index'));
|
372 |
}
|
373 |
}
|
20 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
21 |
$parser = new Twig_Parser($env);
|
22 |
|
23 |
+
$parser->parse($env->tokenize(new Twig_Source($template, 'index')));
|
24 |
}
|
25 |
|
26 |
public function getFailingTestsForAssignment()
|
47 |
public function testArrayExpression($template, $expected)
|
48 |
{
|
49 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
50 |
+
$stream = $env->tokenize(new Twig_Source($template, ''));
|
51 |
$parser = new Twig_Parser($env);
|
52 |
|
53 |
$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr'));
|
62 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
63 |
$parser = new Twig_Parser($env);
|
64 |
|
65 |
+
$parser->parse($env->tokenize(new Twig_Source($template, 'index')));
|
66 |
}
|
67 |
|
68 |
public function getFailingTestsForArray()
|
155 |
public function testStringExpressionDoesNotConcatenateTwoConsecutiveStrings()
|
156 |
{
|
157 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
|
158 |
+
$stream = $env->tokenize(new Twig_Source('{{ "a" "b" }}', 'index'));
|
159 |
$parser = new Twig_Parser($env);
|
160 |
|
161 |
$parser->parse($stream);
|
167 |
public function testStringExpression($template, $expected)
|
168 |
{
|
169 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0));
|
170 |
+
$stream = $env->tokenize(new Twig_Source($template, ''));
|
171 |
$parser = new Twig_Parser($env);
|
172 |
|
173 |
$this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr'));
|
228 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
229 |
$parser = new Twig_Parser($env);
|
230 |
|
231 |
+
$parser->parse($env->tokenize(new Twig_Source('{{ foo.bar(name="Foo") }}', 'index')));
|
232 |
}
|
233 |
|
234 |
/**
|
239 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
240 |
$parser = new Twig_Parser($env);
|
241 |
|
242 |
+
$parser->parse($env->tokenize(new Twig_Source('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index')));
|
243 |
}
|
244 |
|
245 |
/**
|
251 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
252 |
$parser = new Twig_Parser($env);
|
253 |
|
254 |
+
$parser->parse($env->tokenize(new Twig_Source('{% macro foo("a") %}{% endmacro %}', 'index')));
|
255 |
}
|
256 |
|
257 |
/**
|
264 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
265 |
$parser = new Twig_Parser($env);
|
266 |
|
267 |
+
$parser->parse($env->tokenize(new Twig_Source($template, 'index')));
|
268 |
}
|
269 |
|
270 |
public function getMacroDefinitionDoesNotSupportNonConstantDefaultValues()
|
283 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
284 |
$parser = new Twig_Parser($env);
|
285 |
|
286 |
+
$parser->parse($env->tokenize(new Twig_Source($template, 'index')));
|
287 |
}
|
288 |
|
289 |
public function getMacroDefinitionSupportsConstantDefaultValues()
|
308 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
309 |
$parser = new Twig_Parser($env);
|
310 |
|
311 |
+
$parser->parse($env->tokenize(new Twig_Source('{{ cycl() }}', 'index')));
|
312 |
}
|
313 |
|
314 |
/**
|
320 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
321 |
$parser = new Twig_Parser($env);
|
322 |
|
323 |
+
$parser->parse($env->tokenize(new Twig_Source('{{ foobar() }}', 'index')));
|
324 |
}
|
325 |
|
326 |
/**
|
332 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
333 |
$parser = new Twig_Parser($env);
|
334 |
|
335 |
+
$parser->parse($env->tokenize(new Twig_Source('{{ 1|lowe }}', 'index')));
|
336 |
}
|
337 |
|
338 |
/**
|
344 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
345 |
$parser = new Twig_Parser($env);
|
346 |
|
347 |
+
$parser->parse($env->tokenize(new Twig_Source('{{ 1|foobar }}', 'index')));
|
348 |
}
|
349 |
|
350 |
/**
|
355 |
{
|
356 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
357 |
$parser = new Twig_Parser($env);
|
358 |
+
$stream = $env->tokenize(new Twig_Source('{{ 1 is nul }}', 'index'));
|
359 |
+
$parser->parse($stream);
|
360 |
}
|
361 |
|
362 |
/**
|
368 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
369 |
$parser = new Twig_Parser($env);
|
370 |
|
371 |
+
$parser->parse($env->tokenize(new Twig_Source('{{ 1 is foobar }}', 'index')));
|
372 |
}
|
373 |
}
|
library/twig/twig/test/Twig/Tests/Extension/CoreTest.php
CHANGED
@@ -118,7 +118,7 @@ class Twig_Tests_Extension_CoreTest extends PHPUnit_Framework_TestCase
|
|
118 |
public function testCustomEscaper()
|
119 |
{
|
120 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
121 |
-
$twig->getExtension('
|
122 |
|
123 |
$this->assertEquals('fooUTF-8', twig_escape_filter($twig, 'foo', 'foo'));
|
124 |
$this->assertEquals('UTF-8', twig_escape_filter($twig, null, 'foo'));
|
118 |
public function testCustomEscaper()
|
119 |
{
|
120 |
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
121 |
+
$twig->getExtension('Twig_Extension_Core')->setEscaper('foo', 'foo_escaper_for_test');
|
122 |
|
123 |
$this->assertEquals('fooUTF-8', twig_escape_filter($twig, 'foo', 'foo'));
|
124 |
$this->assertEquals('UTF-8', twig_escape_filter($twig, null, 'foo'));
|
library/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
CHANGED
@@ -51,83 +51,146 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
51 |
{
|
52 |
$twig = $this->getEnvironment(false, array(), self::$templates);
|
53 |
$this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally');
|
|
|
54 |
|
|
|
|
|
55 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
56 |
try {
|
57 |
$twig->loadTemplate('1_basic1')->render(self::$params);
|
58 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed method is called');
|
59 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
|
|
60 |
}
|
|
|
61 |
|
|
|
|
|
62 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
63 |
try {
|
64 |
$twig->loadTemplate('1_basic2')->render(self::$params);
|
65 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
|
66 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
67 |
}
|
|
|
68 |
|
|
|
|
|
69 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
70 |
try {
|
71 |
$twig->loadTemplate('1_basic3')->render(self::$params);
|
72 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template');
|
73 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
74 |
}
|
|
|
75 |
|
|
|
|
|
76 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
77 |
try {
|
78 |
$twig->loadTemplate('1_basic4')->render(self::$params);
|
79 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template');
|
80 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
|
|
81 |
}
|
|
|
82 |
|
|
|
|
|
83 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
84 |
try {
|
85 |
$twig->loadTemplate('1_basic5')->render(self::$params);
|
86 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
|
87 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
|
|
88 |
}
|
|
|
89 |
|
|
|
|
|
90 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
91 |
try {
|
92 |
$twig->loadTemplate('1_basic6')->render(self::$params);
|
93 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
|
94 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
|
|
95 |
}
|
|
|
96 |
|
|
|
|
|
97 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
98 |
try {
|
99 |
$twig->loadTemplate('1_basic7')->render(self::$params);
|
100 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed function is called in the template');
|
101 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
102 |
}
|
|
|
103 |
|
|
|
|
|
104 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => 'foo'));
|
105 |
FooObject::reset();
|
106 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods');
|
107 |
$this->assertEquals(1, FooObject::$called['foo'], 'Sandbox only calls method once');
|
|
|
108 |
|
|
|
|
|
109 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => '__toString'));
|
110 |
FooObject::reset();
|
111 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allow some methods');
|
112 |
$this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
|
|
|
113 |
|
|
|
|
|
114 |
$twig = $this->getEnvironment(false, array(), self::$templates);
|
115 |
FooObject::reset();
|
116 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allows __toString when sandbox disabled');
|
117 |
$this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
|
|
|
118 |
|
|
|
|
|
119 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array('upper'));
|
120 |
$this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters');
|
|
|
121 |
|
|
|
|
|
122 |
$twig = $this->getEnvironment(true, array(), self::$templates, array('if'));
|
123 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags');
|
|
|
124 |
|
|
|
|
|
125 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array('FooObject' => 'bar'));
|
126 |
$this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties');
|
|
|
127 |
|
|
|
|
|
128 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array(), array('cycle'));
|
129 |
$this->assertEquals('bar', $twig->loadTemplate('1_basic7')->render(self::$params), 'Sandbox allow some functions');
|
|
|
130 |
|
|
|
|
|
131 |
foreach (array('getfoobar', 'getFoobar', 'getFooBar') as $name) {
|
132 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => $name));
|
133 |
FooObject::reset();
|
@@ -158,6 +221,8 @@ class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
|
|
158 |
$twig->loadTemplate('3_basic')->render(self::$params);
|
159 |
$this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed');
|
160 |
} catch (Twig_Sandbox_SecurityError $e) {
|
|
|
|
|
161 |
}
|
162 |
}
|
163 |
|
51 |
{
|
52 |
$twig = $this->getEnvironment(false, array(), self::$templates);
|
53 |
$this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally');
|
54 |
+
}
|
55 |
|
56 |
+
public function testSandboxUnallowedMethodAccessor()
|
57 |
+
{
|
58 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
59 |
try {
|
60 |
$twig->loadTemplate('1_basic1')->render(self::$params);
|
61 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed method is called');
|
62 |
} catch (Twig_Sandbox_SecurityError $e) {
|
63 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError');
|
64 |
+
$this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class');
|
65 |
+
$this->assertEquals('foo', $e->getMethodName(), 'Exception should be raised on the "foo" method');
|
66 |
}
|
67 |
+
}
|
68 |
|
69 |
+
public function testSandboxUnallowedFilter()
|
70 |
+
{
|
71 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
72 |
try {
|
73 |
$twig->loadTemplate('1_basic2')->render(self::$params);
|
74 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
|
75 |
} catch (Twig_Sandbox_SecurityError $e) {
|
76 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedFilterError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFilterError');
|
77 |
+
$this->assertEquals('upper', $e->getFilterName(), 'Exception should be raised on the "upper" filter');
|
78 |
}
|
79 |
+
}
|
80 |
|
81 |
+
public function testSandboxUnallowedTag()
|
82 |
+
{
|
83 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
84 |
try {
|
85 |
$twig->loadTemplate('1_basic3')->render(self::$params);
|
86 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template');
|
87 |
} catch (Twig_Sandbox_SecurityError $e) {
|
88 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedTagError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedTagError');
|
89 |
+
$this->assertEquals('if', $e->getTagName(), 'Exception should be raised on the "if" tag');
|
90 |
}
|
91 |
+
}
|
92 |
|
93 |
+
public function testSandboxUnallowedProperty()
|
94 |
+
{
|
95 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
96 |
try {
|
97 |
$twig->loadTemplate('1_basic4')->render(self::$params);
|
98 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template');
|
99 |
} catch (Twig_Sandbox_SecurityError $e) {
|
100 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedPropertyError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedPropertyError');
|
101 |
+
$this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class');
|
102 |
+
$this->assertEquals('bar', $e->getPropertyName(), 'Exception should be raised on the "bar" property');
|
103 |
}
|
104 |
+
}
|
105 |
|
106 |
+
public function testSandboxUnallowedToString()
|
107 |
+
{
|
108 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
109 |
try {
|
110 |
$twig->loadTemplate('1_basic5')->render(self::$params);
|
111 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
|
112 |
} catch (Twig_Sandbox_SecurityError $e) {
|
113 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError');
|
114 |
+
$this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class');
|
115 |
+
$this->assertEquals('__tostring', $e->getMethodName(), 'Exception should be raised on the "__toString" method');
|
116 |
}
|
117 |
+
}
|
118 |
|
119 |
+
public function testSandboxUnallowedToStringArray()
|
120 |
+
{
|
121 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
122 |
try {
|
123 |
$twig->loadTemplate('1_basic6')->render(self::$params);
|
124 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
|
125 |
} catch (Twig_Sandbox_SecurityError $e) {
|
126 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError');
|
127 |
+
$this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class');
|
128 |
+
$this->assertEquals('__tostring', $e->getMethodName(), 'Exception should be raised on the "__toString" method');
|
129 |
}
|
130 |
+
}
|
131 |
|
132 |
+
public function testSandboxUnallowedFunction()
|
133 |
+
{
|
134 |
$twig = $this->getEnvironment(true, array(), self::$templates);
|
135 |
try {
|
136 |
$twig->loadTemplate('1_basic7')->render(self::$params);
|
137 |
$this->fail('Sandbox throws a SecurityError exception if an unallowed function is called in the template');
|
138 |
} catch (Twig_Sandbox_SecurityError $e) {
|
139 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedFunctionError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFunctionError');
|
140 |
+
$this->assertEquals('cycle', $e->getFunctionName(), 'Exception should be raised on the "cycle" function');
|
141 |
}
|
142 |
+
}
|
143 |
|
144 |
+
public function testSandboxAllowMethodFoo()
|
145 |
+
{
|
146 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => 'foo'));
|
147 |
FooObject::reset();
|
148 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods');
|
149 |
$this->assertEquals(1, FooObject::$called['foo'], 'Sandbox only calls method once');
|
150 |
+
}
|
151 |
|
152 |
+
public function testSandboxAllowMethodToString()
|
153 |
+
{
|
154 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => '__toString'));
|
155 |
FooObject::reset();
|
156 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allow some methods');
|
157 |
$this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
|
158 |
+
}
|
159 |
|
160 |
+
public function testSandboxAllowMethodToStringDisabled()
|
161 |
+
{
|
162 |
$twig = $this->getEnvironment(false, array(), self::$templates);
|
163 |
FooObject::reset();
|
164 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allows __toString when sandbox disabled');
|
165 |
$this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
|
166 |
+
}
|
167 |
|
168 |
+
public function testSandboxAllowFilter()
|
169 |
+
{
|
170 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array('upper'));
|
171 |
$this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters');
|
172 |
+
}
|
173 |
|
174 |
+
public function testSandboxAllowTag()
|
175 |
+
{
|
176 |
$twig = $this->getEnvironment(true, array(), self::$templates, array('if'));
|
177 |
$this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags');
|
178 |
+
}
|
179 |
|
180 |
+
public function testSandboxAllowProperty()
|
181 |
+
{
|
182 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array('FooObject' => 'bar'));
|
183 |
$this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties');
|
184 |
+
}
|
185 |
|
186 |
+
public function testSandboxAllowFunction()
|
187 |
+
{
|
188 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array(), array('cycle'));
|
189 |
$this->assertEquals('bar', $twig->loadTemplate('1_basic7')->render(self::$params), 'Sandbox allow some functions');
|
190 |
+
}
|
191 |
|
192 |
+
public function testSandboxAllowFunctionsCaseInsensitive()
|
193 |
+
{
|
194 |
foreach (array('getfoobar', 'getFoobar', 'getFooBar') as $name) {
|
195 |
$twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => $name));
|
196 |
FooObject::reset();
|
221 |
$twig->loadTemplate('3_basic')->render(self::$params);
|
222 |
$this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed');
|
223 |
} catch (Twig_Sandbox_SecurityError $e) {
|
224 |
+
$this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedTagError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedTagError');
|
225 |
+
$this->assertEquals('sandbox', $e->getTagName());
|
226 |
}
|
227 |
}
|
228 |
|
library/twig/twig/test/Twig/Tests/Fixtures/autoescape/block.test
CHANGED
@@ -16,6 +16,6 @@ blocks and autoescape
|
|
16 |
--DATA--
|
17 |
return array('br' => '<br />')
|
18 |
--CONFIG--
|
19 |
-
return array('autoescape' => '
|
20 |
--EXPECT--
|
21 |
<br />
|
16 |
--DATA--
|
17 |
return array('br' => '<br />')
|
18 |
--CONFIG--
|
19 |
+
return array('autoescape' => 'name')
|
20 |
--EXPECT--
|
21 |
<br />
|
library/twig/twig/test/Twig/Tests/Fixtures/autoescape/name.test
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"name" autoescape strategy
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ br -}}
|
5 |
+
{{ include('index.html.twig') -}}
|
6 |
+
{{ include('index.txt.twig') -}}
|
7 |
+
--TEMPLATE(index.html.twig)--
|
8 |
+
{{ br -}}
|
9 |
+
--TEMPLATE(index.txt.twig)--
|
10 |
+
{{ br -}}
|
11 |
+
--DATA--
|
12 |
+
return array('br' => '<br />')
|
13 |
+
--CONFIG--
|
14 |
+
return array('autoescape' => 'name')
|
15 |
+
--EXPECT--
|
16 |
+
<br />
|
17 |
+
<br />
|
18 |
+
<br />
|
library/twig/twig/test/Twig/Tests/Fixtures/exceptions/child_contents_outside_blocks.test
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
Exception for child templates defining contents outside blocks defined by parent
|
3 |
+
--TEMPLATE--
|
4 |
+
{% extends 'base.twig' %}
|
5 |
+
|
6 |
+
Content outside a block.
|
7 |
+
|
8 |
+
{% block sidebar %}
|
9 |
+
Content inside a block.
|
10 |
+
{% endblock %}
|
11 |
+
--TEMPLATE(base.twig)--
|
12 |
+
{% block sidebar %}
|
13 |
+
{% endblock %}
|
14 |
+
--EXCEPTION--
|
15 |
+
Twig_Error_Syntax: A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag in "index.twig" at line 3?
|
library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test
CHANGED
@@ -15,4 +15,4 @@ Exception for multiline array with undefined variable
|
|
15 |
--DATA--
|
16 |
return array('foobar' => 'foobar')
|
17 |
--EXCEPTION--
|
18 |
-
Twig_Error_Runtime: Variable "foo2" does not exist in "index.twig" at line 11
|
15 |
--DATA--
|
16 |
return array('foobar' => 'foobar')
|
17 |
--EXCEPTION--
|
18 |
+
Twig_Error_Runtime: Variable "foo2" does not exist in "index.twig" at line 11.
|
library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test
CHANGED
@@ -15,4 +15,4 @@ Exception for multiline array with undefined variable
|
|
15 |
--DATA--
|
16 |
return array()
|
17 |
--EXCEPTION--
|
18 |
-
Twig_Error_Runtime: Variable "foobar" does not exist in "index.twig" at line 7
|
15 |
--DATA--
|
16 |
return array()
|
17 |
--EXCEPTION--
|
18 |
+
Twig_Error_Runtime: Variable "foobar" does not exist in "index.twig" at line 7.
|
library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test
CHANGED
@@ -9,4 +9,4 @@ Foo
|
|
9 |
--DATA--
|
10 |
return array()
|
11 |
--EXCEPTION--
|
12 |
-
Twig_Error_Runtime: Variable "with_context" does not exist in "index.twig" at line 3
|
9 |
--DATA--
|
10 |
return array()
|
11 |
--EXCEPTION--
|
12 |
+
Twig_Error_Runtime: Variable "with_context" does not exist in "index.twig" at line 3.
|
library/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test
CHANGED
@@ -9,4 +9,4 @@ Foo
|
|
9 |
--DATA--
|
10 |
return array()
|
11 |
--EXCEPTION--
|
12 |
-
Twig_Error_Runtime: Variable "vars" does not exist in "index.twig" at line 3
|
9 |
--DATA--
|
10 |
return array()
|
11 |
--EXCEPTION--
|
12 |
+
Twig_Error_Runtime: Variable "vars" does not exist in "index.twig" at line 3.
|
library/twig/twig/test/Twig/Tests/Fixtures/expressions/magic_call.test
CHANGED
@@ -6,21 +6,21 @@ Twig supports __call() for attributes
|
|
6 |
--DATA--
|
7 |
class TestClassForMagicCallAttributes
|
8 |
{
|
9 |
-
|
10 |
-
{
|
11 |
-
return 'bar_from_getbar';
|
12 |
-
}
|
13 |
-
|
14 |
-
public function __call($method, $arguments)
|
15 |
-
{
|
16 |
-
if ('foo' === $method)
|
17 |
{
|
18 |
-
|
19 |
}
|
20 |
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
}
|
|
|
24 |
return array('foo' => new TestClassForMagicCallAttributes())
|
25 |
--EXPECT--
|
26 |
foo_from_call
|
6 |
--DATA--
|
7 |
class TestClassForMagicCallAttributes
|
8 |
{
|
9 |
+
public function getBar()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
{
|
11 |
+
return 'bar_from_getbar';
|
12 |
}
|
13 |
|
14 |
+
public function __call($method, $arguments)
|
15 |
+
{
|
16 |
+
if ('foo' === $method) {
|
17 |
+
return 'foo_from_call';
|
18 |
+
}
|
19 |
+
|
20 |
+
return false;
|
21 |
+
}
|
22 |
}
|
23 |
+
|
24 |
return array('foo' => new TestClassForMagicCallAttributes())
|
25 |
--EXPECT--
|
26 |
foo_from_call
|
library/twig/twig/test/Twig/Tests/Fixtures/expressions/power.test
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
Twig parses power expressions
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ 2**3 }}
|
5 |
+
{{ (-2)**3 }}
|
6 |
+
{{ (-2)**(-3) }}
|
7 |
+
{{ a ** a }}
|
8 |
+
{{ a ** b }}
|
9 |
+
{{ b ** a }}
|
10 |
+
{{ b ** b }}
|
11 |
+
--DATA--
|
12 |
+
return array('a' => 4, 'b' => -2);
|
13 |
+
--EXPECT--
|
14 |
+
8
|
15 |
+
-8
|
16 |
+
-0.125
|
17 |
+
256
|
18 |
+
0.0625
|
19 |
+
16
|
20 |
+
0.25
|
library/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format.test
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
{{ date1|date('d/m/Y') }}
|
6 |
--DATA--
|
7 |
date_default_timezone_set('UTC');
|
8 |
-
$twig->getExtension('
|
9 |
return array(
|
10 |
'date1' => mktime(13, 45, 0, 10, 4, 2010),
|
11 |
)
|
5 |
{{ date1|date('d/m/Y') }}
|
6 |
--DATA--
|
7 |
date_default_timezone_set('UTC');
|
8 |
+
$twig->getExtension('Twig_Extension_Core')->setDateFormat('Y-m-d', '%d days %h hours');
|
9 |
return array(
|
10 |
'date1' => mktime(13, 45, 0, 10, 4, 2010),
|
11 |
)
|
library/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test
CHANGED
@@ -7,7 +7,7 @@ version_compare(phpversion(), '5.3.0', '>=')
|
|
7 |
{{ date2|date('%d days') }}
|
8 |
--DATA--
|
9 |
date_default_timezone_set('UTC');
|
10 |
-
$twig->getExtension('
|
11 |
return array(
|
12 |
'date2' => new DateInterval('P2D'),
|
13 |
)
|
7 |
{{ date2|date('%d days') }}
|
8 |
--DATA--
|
9 |
date_default_timezone_set('UTC');
|
10 |
+
$twig->getExtension('Twig_Extension_Core')->setDateFormat('Y-m-d', '%d days %h hours');
|
11 |
return array(
|
12 |
'date2' => new DateInterval('P2D'),
|
13 |
)
|
library/twig/twig/test/Twig/Tests/Fixtures/filters/number_format_default.test
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
{{ 1020.25|number_format(2, ',') }}
|
10 |
{{ 1020.25|number_format(2, ',', '.') }}
|
11 |
--DATA--
|
12 |
-
$twig->getExtension('
|
13 |
return array();
|
14 |
--EXPECT--
|
15 |
20!00
|
9 |
{{ 1020.25|number_format(2, ',') }}
|
10 |
{{ 1020.25|number_format(2, ',', '.') }}
|
11 |
--DATA--
|
12 |
+
$twig->getExtension('Twig_Extension_Core')->setNumberFormat(2, '!', '=');
|
13 |
return array();
|
14 |
--EXPECT--
|
15 |
20!00
|
library/twig/twig/test/Twig/Tests/Fixtures/filters/static_calls.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
Filters as static method calls
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ 'foo'|static_call_string }}
|
5 |
+
{{ 'foo'|static_call_array }}
|
6 |
+
--DATA--
|
7 |
+
return array('foo' => 'foo')
|
8 |
+
--EXPECT--
|
9 |
+
*foo*
|
10 |
+
*foo*
|
library/twig/twig/test/Twig/Tests/Fixtures/functions/block_with_template.test
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"block" function with a template argument
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ block('foo', 'included.twig') }}
|
5 |
+
{{ block('foo', included_loaded) }}
|
6 |
+
{{ block('foo', included_loaded_internal) }}
|
7 |
+
{% set output = block('foo', 'included.twig') %}
|
8 |
+
{{ output }}
|
9 |
+
{% block foo %}NOT FOO{% endblock %}
|
10 |
+
--TEMPLATE(included.twig)--
|
11 |
+
{% block foo %}FOO{% endblock %}
|
12 |
+
--DATA--
|
13 |
+
return array(
|
14 |
+
'included_loaded' => $twig->load('included.twig'),
|
15 |
+
'included_loaded_internal' => $twig->loadTemplate('included.twig'),
|
16 |
+
)
|
17 |
+
--EXPECT--
|
18 |
+
FOO
|
19 |
+
FOO
|
20 |
+
FOO
|
21 |
+
FOO
|
22 |
+
NOT FOO
|
library/twig/twig/test/Twig/Tests/Fixtures/functions/block_without_name.test
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"block" function without arguments
|
3 |
+
--TEMPLATE--
|
4 |
+
{% extends 'base.twig' %}
|
5 |
+
{% block bar %}BAR{% endblock %}
|
6 |
+
--TEMPLATE(base.twig)--
|
7 |
+
{% block foo %}{{ block() }}{% endblock %}
|
8 |
+
{% block bar %}BAR_BASE{% endblock %}
|
9 |
+
--DATA--
|
10 |
+
return array()
|
11 |
+
--EXCEPTION--
|
12 |
+
Twig_Error_Syntax: The "block" function takes one argument (the block name) in "base.twig" at line 2.
|
library/twig/twig/test/Twig/Tests/Fixtures/functions/date.test
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
--TEST--
|
2 |
"date" function
|
3 |
--TEMPLATE--
|
4 |
-
{{ date() == date('now') ? 'OK' : 'KO' }}
|
5 |
{{ date(date1) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
6 |
{{ date(date2) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
7 |
{{ date(date3) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
1 |
--TEST--
|
2 |
"date" function
|
3 |
--TEMPLATE--
|
4 |
+
{{ date().format('r') == date('now').format('r') ? 'OK' : 'KO' }}
|
5 |
{{ date(date1) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
6 |
{{ date(date2) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
7 |
{{ date(date3) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
library/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call.test
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
__call calls
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ 'foo'|magic_call }}
|
5 |
+
--DATA--
|
6 |
+
return array()
|
7 |
+
--EXPECT--
|
8 |
+
magic_foo
|
library/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call53.test
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
__staticCall calls
|
3 |
+
--CONDITION--
|
4 |
+
version_compare(phpversion(), '5.3.0', '>=')
|
5 |
+
--TEMPLATE--
|
6 |
+
{{ 'foo'|magic_call_string }}
|
7 |
+
{{ 'foo'|magic_call_array }}
|
8 |
+
--DATA--
|
9 |
+
return array()
|
10 |
+
--EXPECT--
|
11 |
+
static_magic_foo
|
12 |
+
static_magic_foo
|
library/twig/twig/test/Twig/Tests/Fixtures/functions/static_calls.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
Functions as static method calls
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ static_call_string('foo') }}
|
5 |
+
{{ static_call_array('foo') }}
|
6 |
+
--DATA--
|
7 |
+
return array('foo' => 'foo')
|
8 |
+
--EXPECT--
|
9 |
+
*foo*
|
10 |
+
*foo*
|
library/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test
CHANGED
@@ -5,4 +5,3 @@ macro with varargs argument
|
|
5 |
{% endmacro %}
|
6 |
--EXCEPTION--
|
7 |
Twig_Error_Syntax: The argument "varargs" in macro "test" cannot be defined because the variable "varargs" is reserved for arbitrary arguments in "index.twig" at line 2.
|
8 |
-
|
5 |
{% endmacro %}
|
6 |
--EXCEPTION--
|
7 |
Twig_Error_Syntax: The argument "varargs" in macro "test" cannot be defined because the variable "varargs" is reserved for arbitrary arguments in "index.twig" at line 2.
|
|
library/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test
CHANGED
@@ -12,4 +12,4 @@ foo
|
|
12 |
--DATA--
|
13 |
return array('foo' => 'foo');
|
14 |
--EXCEPTION--
|
15 |
-
Twig_Error_Runtime: Impossible to access an attribute ("bar") on a string variable ("foo") in "foo" at line 3
|
12 |
--DATA--
|
13 |
return array('foo' => 'foo');
|
14 |
--EXCEPTION--
|
15 |
+
Twig_Error_Runtime: Impossible to access an attribute ("bar") on a string variable ("foo") in "foo" at line 3.
|
library/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test
CHANGED
@@ -13,4 +13,4 @@ BAR
|
|
13 |
--DATA--
|
14 |
return array()
|
15 |
--EXCEPTION--
|
16 |
-
Twig_Error_Runtime: Variable "nothing" does not exist in "index.twig" at line 5
|
13 |
--DATA--
|
14 |
return array()
|
15 |
--EXCEPTION--
|
16 |
+
Twig_Error_Runtime: Variable "nothing" does not exist in "index.twig" at line 5.
|
library/twig/twig/test/Twig/Tests/Fixtures/tags/with/basic.test
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"with" tag
|
3 |
+
--TEMPLATE--
|
4 |
+
{% with %}
|
5 |
+
{% set bar = 'BAZ' %}
|
6 |
+
{{ foo }}{{ bar }}
|
7 |
+
{% endwith %}
|
8 |
+
{{ foo }}{{ bar }}
|
9 |
+
--DATA--
|
10 |
+
return array('foo' => 'foo', 'bar' => 'bar')
|
11 |
+
--EXPECT--
|
12 |
+
fooBAZ
|
13 |
+
foobar
|
library/twig/twig/test/Twig/Tests/Fixtures/tags/with/expression.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"with" tag with expression
|
3 |
+
--TEMPLATE--
|
4 |
+
{% with {foo: 'foo', bar: 'BAZ'} %}
|
5 |
+
{{ foo }}{{ bar }}
|
6 |
+
{% endwith %}
|
7 |
+
--DATA--
|
8 |
+
return array('foo' => 'baz')
|
9 |
+
--EXPECT--
|
10 |
+
fooBAZ
|
library/twig/twig/test/Twig/Tests/Fixtures/tags/with/nested.test
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
nested "with" tags
|
3 |
+
--TEMPLATE--
|
4 |
+
{% set foo, bar = 'foo', 'bar' %}
|
5 |
+
{% with {bar: 'BAZ'} %}
|
6 |
+
{% with {foo: 'FOO'} %}
|
7 |
+
{{ foo }}{{ bar }}
|
8 |
+
{% endwith %}
|
9 |
+
{% endwith %}
|
10 |
+
{{ foo }}{{ bar }}
|
11 |
+
--DATA--
|
12 |
+
return array()
|
13 |
+
--EXPECT--
|
14 |
+
FOOBAZ
|
15 |
+
foobar
|
library/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_no_hash.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"with" tag with an expression that is not a hash
|
3 |
+
--TEMPLATE--
|
4 |
+
{% with vars %}
|
5 |
+
{{ foo }}{{ bar }}
|
6 |
+
{% endwith %}
|
7 |
+
--DATA--
|
8 |
+
return array('vars' => 'no-hash')
|
9 |
+
--EXCEPTION--
|
10 |
+
Twig_Error_Runtime: Variables passed to the "with" tag must be a hash in "index.twig" at line 2.
|
library/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_only.test
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"with" tag with expression and only
|
3 |
+
--TEMPLATE--
|
4 |
+
{% with {foo: 'foo', bar: 'BAZ'} only %}
|
5 |
+
{{ foo }}{{ bar }}{{ baz }}
|
6 |
+
{% endwith %}
|
7 |
+
--DATA--
|
8 |
+
return array('foo' => 'baz', 'baz' => 'baz')
|
9 |
+
--EXCEPTION--
|
10 |
+
Twig_Error_Runtime: Variable "baz" does not exist in "index.twig" at line 3.
|
library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_attribute.test
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"defined" support for attribute
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ attribute(nested, "definedVar") is defined ? 'ok' : 'ko' }}
|
5 |
+
{{ attribute(nested, "undefinedVar") is not defined ? 'ok' : 'ko' }}
|
6 |
+
{{ attribute(nested, definedVarName) is defined ? 'ok' : 'ko' }}
|
7 |
+
{{ attribute(nested, undefinedVarName) is not defined ? 'ok' : 'ko' }}
|
8 |
+
--DATA--
|
9 |
+
return array(
|
10 |
+
'nested' => array(
|
11 |
+
'definedVar' => 'defined',
|
12 |
+
),
|
13 |
+
'definedVarName' => 'definedVar',
|
14 |
+
'undefinedVarName' => 'undefinedVar',
|
15 |
+
);
|
16 |
+
--EXPECT--
|
17 |
+
ok
|
18 |
+
ok
|
19 |
+
ok
|
20 |
+
ok
|
21 |
+
--DATA--
|
22 |
+
return array(
|
23 |
+
'nested' => array(
|
24 |
+
'definedVar' => 'defined',
|
25 |
+
),
|
26 |
+
'definedVarName' => 'definedVar',
|
27 |
+
'undefinedVarName' => 'undefinedVar',
|
28 |
+
);
|
29 |
+
--CONFIG--
|
30 |
+
return array('strict_variables' => false)
|
31 |
+
--EXPECT--
|
32 |
+
ok
|
33 |
+
ok
|
34 |
+
ok
|
35 |
+
ok
|
library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks.test
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"defined" support for blocks
|
3 |
+
--TEMPLATE--
|
4 |
+
{% extends 'parent' %}
|
5 |
+
{% block icon %}icon{% endblock %}
|
6 |
+
{% block body %}
|
7 |
+
{{ parent() }}
|
8 |
+
{{ block('foo') is defined ? 'ok' : 'ko' }}
|
9 |
+
{{ block('footer') is defined ? 'ok' : 'ko' }}
|
10 |
+
{{ block('icon') is defined ? 'ok' : 'ko' }}
|
11 |
+
{{ block('block1') is defined ? 'ok' : 'ko' }}
|
12 |
+
{%- embed 'embed' %}
|
13 |
+
{% block content %}content{% endblock %}
|
14 |
+
{% endembed %}
|
15 |
+
{% endblock %}
|
16 |
+
{% use 'blocks' %}
|
17 |
+
--TEMPLATE(parent)--
|
18 |
+
{% block body %}
|
19 |
+
{{ block('icon') is defined ? 'ok' : 'ko' -}}
|
20 |
+
{% endblock %}
|
21 |
+
{% block footer %}{% endblock %}
|
22 |
+
--TEMPLATE(embed)--
|
23 |
+
{{ block('icon') is defined ? 'ok' : 'ko' }}
|
24 |
+
{{ block('content') is defined ? 'ok' : 'ko' }}
|
25 |
+
{{ block('block1') is defined ? 'ok' : 'ko' }}
|
26 |
+
--TEMPLATE(blocks)--
|
27 |
+
{% block block1 %}{%endblock %}
|
28 |
+
--DATA--
|
29 |
+
return array()
|
30 |
+
--EXPECT--
|
31 |
+
ok
|
32 |
+
ko
|
33 |
+
ok
|
34 |
+
ok
|
35 |
+
ok
|
36 |
+
ko
|
37 |
+
ok
|
38 |
+
ko
|
library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"defined" support for blocks with a template argument
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ block('foo', 'included.twig') is defined ? 'ok' : 'ko' }}
|
5 |
+
{{ block('foo', included_loaded) is defined ? 'ok' : 'ko' }}
|
6 |
+
{{ block('foo', included_loaded_internal) is defined ? 'ok' : 'ko' }}
|
7 |
+
--TEMPLATE(included.twig)--
|
8 |
+
{% block foo %}FOO{% endblock %}
|
9 |
+
--DATA--
|
10 |
+
return array(
|
11 |
+
'included_loaded' => $twig->load('included.twig'),
|
12 |
+
'included_loaded_internal' => $twig->loadTemplate('included.twig'),
|
13 |
+
)
|
14 |
+
--EXPECT--
|
15 |
+
ok
|
16 |
+
ok
|
17 |
+
ok
|
library/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_constants.test
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"defined" support for constants
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ constant('DATE_W3C') is defined ? 'ok' : 'ko' }}
|
5 |
+
{{ constant('ARRAY_AS_PROPS', object) is defined ? 'ok' : 'ko' }}
|
6 |
+
{{ constant('FOOBAR') is not defined ? 'ok' : 'ko' }}
|
7 |
+
{{ constant('FOOBAR', object) is not defined ? 'ok' : 'ko' }}
|
8 |
+
--DATA--
|
9 |
+
return array('expect' => DATE_W3C, 'object' => new ArrayObject(array('hi')));
|
10 |
+
--EXPECT--
|
11 |
+
ok
|
12 |
+
ok
|
13 |
+
ok
|
14 |
+
ok
|
library/twig/twig/test/Twig/Tests/IntegrationTest.php
CHANGED
@@ -141,6 +141,11 @@ class TwigTestExtension extends Twig_Extension
|
|
141 |
new Twig_SimpleFilter('nl2br', array($this, 'nl2br'), array('pre_escape' => 'html', 'is_safe' => array('html'))),
|
142 |
new Twig_SimpleFilter('escape_something', array($this, 'escape_something'), array('is_safe' => array('something'))),
|
143 |
new Twig_SimpleFilter('preserves_safety', array($this, 'preserves_safety'), array('preserves_safety' => array('html'))),
|
|
|
|
|
|
|
|
|
|
|
144 |
new Twig_SimpleFilter('*_path', array($this, 'dynamic_path')),
|
145 |
new Twig_SimpleFilter('*_foo_*_bar', array($this, 'dynamic_foo')),
|
146 |
);
|
@@ -152,6 +157,8 @@ class TwigTestExtension extends Twig_Extension
|
|
152 |
new Twig_SimpleFunction('§', array($this, '§Function')),
|
153 |
new Twig_SimpleFunction('safe_br', array($this, 'br'), array('is_safe' => array('html'))),
|
154 |
new Twig_SimpleFunction('unsafe_br', array($this, 'br')),
|
|
|
|
|
155 |
new Twig_SimpleFunction('*_path', array($this, 'dynamic_path')),
|
156 |
new Twig_SimpleFunction('*_foo_*_bar', array($this, 'dynamic_foo')),
|
157 |
);
|
@@ -212,6 +219,11 @@ class TwigTestExtension extends Twig_Extension
|
|
212 |
return strtoupper($value);
|
213 |
}
|
214 |
|
|
|
|
|
|
|
|
|
|
|
215 |
public function br()
|
216 |
{
|
217 |
return '<br />';
|
@@ -222,8 +234,21 @@ class TwigTestExtension extends Twig_Extension
|
|
222 |
return false !== strpos($value, ' ');
|
223 |
}
|
224 |
|
225 |
-
public function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
{
|
227 |
-
|
|
|
|
|
|
|
|
|
228 |
}
|
229 |
}
|
141 |
new Twig_SimpleFilter('nl2br', array($this, 'nl2br'), array('pre_escape' => 'html', 'is_safe' => array('html'))),
|
142 |
new Twig_SimpleFilter('escape_something', array($this, 'escape_something'), array('is_safe' => array('something'))),
|
143 |
new Twig_SimpleFilter('preserves_safety', array($this, 'preserves_safety'), array('preserves_safety' => array('html'))),
|
144 |
+
new Twig_SimpleFilter('static_call_string', 'TwigTestExtension::staticCall'),
|
145 |
+
new Twig_SimpleFilter('static_call_array', array('TwigTestExtension', 'staticCall')),
|
146 |
+
new Twig_SimpleFilter('magic_call', array($this, 'magicCall')),
|
147 |
+
new Twig_SimpleFilter('magic_call_string', 'TwigTestExtension::magicStaticCall'),
|
148 |
+
new Twig_SimpleFilter('magic_call_array', array('TwigTestExtension', 'magicStaticCall')),
|
149 |
new Twig_SimpleFilter('*_path', array($this, 'dynamic_path')),
|
150 |
new Twig_SimpleFilter('*_foo_*_bar', array($this, 'dynamic_foo')),
|
151 |
);
|
157 |
new Twig_SimpleFunction('§', array($this, '§Function')),
|
158 |
new Twig_SimpleFunction('safe_br', array($this, 'br'), array('is_safe' => array('html'))),
|
159 |
new Twig_SimpleFunction('unsafe_br', array($this, 'br')),
|
160 |
+
new Twig_SimpleFunction('static_call_string', 'TwigTestExtension::staticCall'),
|
161 |
+
new Twig_SimpleFunction('static_call_array', array('TwigTestExtension', 'staticCall')),
|
162 |
new Twig_SimpleFunction('*_path', array($this, 'dynamic_path')),
|
163 |
new Twig_SimpleFunction('*_foo_*_bar', array($this, 'dynamic_foo')),
|
164 |
);
|
219 |
return strtoupper($value);
|
220 |
}
|
221 |
|
222 |
+
public static function staticCall($value)
|
223 |
+
{
|
224 |
+
return "*$value*";
|
225 |
+
}
|
226 |
+
|
227 |
public function br()
|
228 |
{
|
229 |
return '<br />';
|
234 |
return false !== strpos($value, ' ');
|
235 |
}
|
236 |
|
237 |
+
public function __call($method, $arguments)
|
238 |
+
{
|
239 |
+
if ('magicCall' !== $method) {
|
240 |
+
throw new BadMethodCallException('Unexpected call to __call');
|
241 |
+
}
|
242 |
+
|
243 |
+
return 'magic_'.$arguments[0];
|
244 |
+
}
|
245 |
+
|
246 |
+
public static function __callStatic($method, $arguments)
|
247 |
{
|
248 |
+
if ('magicStaticCall' !== $method) {
|
249 |
+
throw new BadMethodCallException('Unexpected call to __callStatic');
|
250 |
+
}
|
251 |
+
|
252 |
+
return 'static_magic_'.$arguments[0];
|
253 |
}
|
254 |
}
|
library/twig/twig/test/Twig/Tests/LegacyFixtures/autoescape/filename.legacy.test
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
--TEST--
|
2 |
+
"filename" autoescape strategy
|
3 |
+
--TEMPLATE--
|
4 |
+
{{ br -}}
|
5 |
+
{{ include('index.html.twig') -}}
|
6 |
+
{{ include('index.txt.twig') -}}
|
7 |
+
--TEMPLATE(index.html.twig)--
|
8 |
+
{{ br -}}
|
9 |
+
--TEMPLATE(index.txt.twig)--
|
10 |
+
{{ br -}}
|
11 |
+
--DATA--
|
12 |
+
return array('br' => '<br />')
|
13 |
+
--CONFIG--
|
14 |
+
return array('autoescape' => 'filename')
|
15 |
+
--EXPECT--
|
16 |
+
<br />
|
17 |
+
<br />
|
18 |
+
<br />
|
library/twig/twig/test/Twig/Tests/LexerTest.php
CHANGED
@@ -10,12 +10,23 @@
|
|
10 |
*/
|
11 |
class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
12 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
public function testNameLabelForTag()
|
14 |
{
|
15 |
$template = '{% § %}';
|
16 |
|
17 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
18 |
-
$stream = $lexer->tokenize($template);
|
19 |
|
20 |
$stream->expect(Twig_Token::BLOCK_START_TYPE);
|
21 |
$this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
|
@@ -26,7 +37,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
26 |
$template = '{{ §() }}';
|
27 |
|
28 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
29 |
-
$stream = $lexer->tokenize($template);
|
30 |
|
31 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
32 |
$this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
|
@@ -43,7 +54,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
43 |
protected function countToken($template, $type, $value = null)
|
44 |
{
|
45 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
46 |
-
$stream = $lexer->tokenize($template);
|
47 |
|
48 |
$count = 0;
|
49 |
while (!$stream->isEOF()) {
|
@@ -68,7 +79,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
68 |
."}}\n";
|
69 |
|
70 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
71 |
-
$stream = $lexer->tokenize($template);
|
72 |
|
73 |
// foo\nbar\n
|
74 |
$this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
@@ -88,7 +99,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
88 |
."}}\n";
|
89 |
|
90 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
91 |
-
$stream = $lexer->tokenize($template);
|
92 |
|
93 |
// foo\nbar
|
94 |
$this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
@@ -103,7 +114,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
103 |
$template = '{# '.str_repeat('*', 100000).' #}';
|
104 |
|
105 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
106 |
-
$lexer->tokenize($template);
|
107 |
|
108 |
// should not throw an exception
|
109 |
}
|
@@ -113,7 +124,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
113 |
$template = '{% verbatim %}'.str_repeat('*', 100000).'{% endverbatim %}';
|
114 |
|
115 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
116 |
-
$lexer->tokenize($template);
|
117 |
|
118 |
// should not throw an exception
|
119 |
}
|
@@ -123,7 +134,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
123 |
$template = '{{ '.str_repeat('x', 100000).' }}';
|
124 |
|
125 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
126 |
-
$lexer->tokenize($template);
|
127 |
|
128 |
// should not throw an exception
|
129 |
}
|
@@ -133,7 +144,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
133 |
$template = '{% '.str_repeat('x', 100000).' %}';
|
134 |
|
135 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
136 |
-
$lexer->tokenize($template);
|
137 |
|
138 |
// should not throw an exception
|
139 |
}
|
@@ -143,7 +154,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
143 |
$template = '{{ 922337203685477580700 }}';
|
144 |
|
145 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
146 |
-
$stream = $lexer->tokenize($template);
|
147 |
$stream->next();
|
148 |
$node = $stream->next();
|
149 |
$this->assertEquals('922337203685477580700', $node->getValue());
|
@@ -157,7 +168,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
157 |
);
|
158 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
159 |
foreach ($tests as $template => $expected) {
|
160 |
-
$stream = $lexer->tokenize($template);
|
161 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
162 |
$stream->expect(Twig_Token::STRING_TYPE, $expected);
|
163 |
}
|
@@ -168,7 +179,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
168 |
$template = 'foo {{ "bar #{ baz + 1 }" }}';
|
169 |
|
170 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
171 |
-
$stream = $lexer->tokenize($template);
|
172 |
$stream->expect(Twig_Token::TEXT_TYPE, 'foo ');
|
173 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
174 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
@@ -185,7 +196,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
185 |
$template = '{{ "bar \#{baz+1}" }}';
|
186 |
|
187 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
188 |
-
$stream = $lexer->tokenize($template);
|
189 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
190 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar #{baz+1}');
|
191 |
$stream->expect(Twig_Token::VAR_END_TYPE);
|
@@ -196,7 +207,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
196 |
$template = '{{ "bar # baz" }}';
|
197 |
|
198 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
199 |
-
$stream = $lexer->tokenize($template);
|
200 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
201 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar # baz');
|
202 |
$stream->expect(Twig_Token::VAR_END_TYPE);
|
@@ -211,7 +222,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
211 |
$template = '{{ "bar #{x" }}';
|
212 |
|
213 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
214 |
-
$lexer->tokenize($template);
|
215 |
}
|
216 |
|
217 |
public function testStringWithNestedInterpolations()
|
@@ -219,7 +230,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
219 |
$template = '{{ "bar #{ "foo#{bar}" }" }}';
|
220 |
|
221 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
222 |
-
$stream = $lexer->tokenize($template);
|
223 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
224 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
225 |
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
@@ -236,7 +247,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
236 |
$template = '{% foo "bar #{ "foo#{bar}" }" %}';
|
237 |
|
238 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
239 |
-
$stream = $lexer->tokenize($template);
|
240 |
$stream->expect(Twig_Token::BLOCK_START_TYPE);
|
241 |
$stream->expect(Twig_Token::NAME_TYPE, 'foo');
|
242 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
@@ -254,7 +265,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
254 |
$template = "{{ 1 and\n0}}";
|
255 |
|
256 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
257 |
-
$stream = $lexer->tokenize($template);
|
258 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
259 |
$stream->expect(Twig_Token::NUMBER_TYPE, 1);
|
260 |
$stream->expect(Twig_Token::OPERATOR_TYPE, 'and');
|
@@ -262,7 +273,7 @@ class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
|
262 |
|
263 |
/**
|
264 |
* @expectedException Twig_Error_Syntax
|
265 |
-
* @expectedExceptionMessage Unclosed "variable" at line 3
|
266 |
*/
|
267 |
public function testUnterminatedVariable()
|
268 |
{
|
@@ -276,12 +287,12 @@ bar
|
|
276 |
';
|
277 |
|
278 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
279 |
-
$lexer->tokenize($template);
|
280 |
}
|
281 |
|
282 |
/**
|
283 |
* @expectedException Twig_Error_Syntax
|
284 |
-
* @expectedExceptionMessage Unclosed "block" at line 3
|
285 |
*/
|
286 |
public function testUnterminatedBlock()
|
287 |
{
|
@@ -295,6 +306,6 @@ bar
|
|
295 |
';
|
296 |
|
297 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
298 |
-
$lexer->tokenize($template);
|
299 |
}
|
300 |
}
|
10 |
*/
|
11 |
class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase
|
12 |
{
|
13 |
+
/**
|
14 |
+
* @group legacy
|
15 |
+
*/
|
16 |
+
public function testLegacyConstructorSignature()
|
17 |
+
{
|
18 |
+
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
19 |
+
$stream = $lexer->tokenize('{{ foo }}', 'foo');
|
20 |
+
$this->assertEquals('foo', $stream->getFilename());
|
21 |
+
$this->assertEquals('{{ foo }}', $stream->getSource());
|
22 |
+
}
|
23 |
+
|
24 |
public function testNameLabelForTag()
|
25 |
{
|
26 |
$template = '{% § %}';
|
27 |
|
28 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
29 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
30 |
|
31 |
$stream->expect(Twig_Token::BLOCK_START_TYPE);
|
32 |
$this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
|
37 |
$template = '{{ §() }}';
|
38 |
|
39 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
40 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
41 |
|
42 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
43 |
$this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
|
54 |
protected function countToken($template, $type, $value = null)
|
55 |
{
|
56 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
57 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
58 |
|
59 |
$count = 0;
|
60 |
while (!$stream->isEOF()) {
|
79 |
."}}\n";
|
80 |
|
81 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
82 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
83 |
|
84 |
// foo\nbar\n
|
85 |
$this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
99 |
."}}\n";
|
100 |
|
101 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
102 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
103 |
|
104 |
// foo\nbar
|
105 |
$this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
|
114 |
$template = '{# '.str_repeat('*', 100000).' #}';
|
115 |
|
116 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
117 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
118 |
|
119 |
// should not throw an exception
|
120 |
}
|
124 |
$template = '{% verbatim %}'.str_repeat('*', 100000).'{% endverbatim %}';
|
125 |
|
126 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
127 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
128 |
|
129 |
// should not throw an exception
|
130 |
}
|
134 |
$template = '{{ '.str_repeat('x', 100000).' }}';
|
135 |
|
136 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
137 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
138 |
|
139 |
// should not throw an exception
|
140 |
}
|
144 |
$template = '{% '.str_repeat('x', 100000).' %}';
|
145 |
|
146 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
147 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
148 |
|
149 |
// should not throw an exception
|
150 |
}
|
154 |
$template = '{{ 922337203685477580700 }}';
|
155 |
|
156 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
157 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
158 |
$stream->next();
|
159 |
$node = $stream->next();
|
160 |
$this->assertEquals('922337203685477580700', $node->getValue());
|
168 |
);
|
169 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
170 |
foreach ($tests as $template => $expected) {
|
171 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
172 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
173 |
$stream->expect(Twig_Token::STRING_TYPE, $expected);
|
174 |
}
|
179 |
$template = 'foo {{ "bar #{ baz + 1 }" }}';
|
180 |
|
181 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
182 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
183 |
$stream->expect(Twig_Token::TEXT_TYPE, 'foo ');
|
184 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
185 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
196 |
$template = '{{ "bar \#{baz+1}" }}';
|
197 |
|
198 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
199 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
200 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
201 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar #{baz+1}');
|
202 |
$stream->expect(Twig_Token::VAR_END_TYPE);
|
207 |
$template = '{{ "bar # baz" }}';
|
208 |
|
209 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
210 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
211 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
212 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar # baz');
|
213 |
$stream->expect(Twig_Token::VAR_END_TYPE);
|
222 |
$template = '{{ "bar #{x" }}';
|
223 |
|
224 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
225 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
226 |
}
|
227 |
|
228 |
public function testStringWithNestedInterpolations()
|
230 |
$template = '{{ "bar #{ "foo#{bar}" }" }}';
|
231 |
|
232 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
233 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
234 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
235 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
236 |
$stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
|
247 |
$template = '{% foo "bar #{ "foo#{bar}" }" %}';
|
248 |
|
249 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
250 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
251 |
$stream->expect(Twig_Token::BLOCK_START_TYPE);
|
252 |
$stream->expect(Twig_Token::NAME_TYPE, 'foo');
|
253 |
$stream->expect(Twig_Token::STRING_TYPE, 'bar ');
|
265 |
$template = "{{ 1 and\n0}}";
|
266 |
|
267 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
268 |
+
$stream = $lexer->tokenize(new Twig_Source($template, 'index'));
|
269 |
$stream->expect(Twig_Token::VAR_START_TYPE);
|
270 |
$stream->expect(Twig_Token::NUMBER_TYPE, 1);
|
271 |
$stream->expect(Twig_Token::OPERATOR_TYPE, 'and');
|
273 |
|
274 |
/**
|
275 |
* @expectedException Twig_Error_Syntax
|
276 |
+
* @expectedExceptionMessage Unclosed "variable" in "index" at line 3
|
277 |
*/
|
278 |
public function testUnterminatedVariable()
|
279 |
{
|
287 |
';
|
288 |
|
289 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
290 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
291 |
}
|
292 |
|
293 |
/**
|
294 |
* @expectedException Twig_Error_Syntax
|
295 |
+
* @expectedExceptionMessage Unclosed "block" in "index" at line 3
|
296 |
*/
|
297 |
public function testUnterminatedBlock()
|
298 |
{
|
306 |
';
|
307 |
|
308 |
$lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
309 |
+
$lexer->tokenize(new Twig_Source($template, 'index'));
|
310 |
}
|
311 |
}
|
library/twig/twig/test/Twig/Tests/Loader/ArrayTest.php
CHANGED
@@ -11,6 +11,9 @@
|
|
11 |
|
12 |
class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
|
|
|
|
|
|
14 |
public function testGetSource()
|
15 |
{
|
16 |
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
@@ -19,6 +22,7 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
|
19 |
}
|
20 |
|
21 |
/**
|
|
|
22 |
* @expectedException Twig_Error_Loader
|
23 |
*/
|
24 |
public function testGetSourceWhenTemplateDoesNotExist()
|
@@ -28,6 +32,16 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
|
28 |
$loader->getSource('foo');
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
public function testGetCacheKey()
|
32 |
{
|
33 |
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
@@ -50,7 +64,7 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
|
50 |
$loader = new Twig_Loader_Array(array());
|
51 |
$loader->setTemplate('foo', 'bar');
|
52 |
|
53 |
-
$this->assertEquals('bar', $loader->
|
54 |
}
|
55 |
|
56 |
public function testIsFresh()
|
@@ -75,7 +89,7 @@ class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
|
75 |
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
76 |
|
77 |
$loader->getCacheKey($name);
|
78 |
-
$loader->
|
79 |
$loader->isFresh($name, time());
|
80 |
$loader->setTemplate($name, 'foobar');
|
81 |
}
|
11 |
|
12 |
class Twig_Tests_Loader_ArrayTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
+
/**
|
15 |
+
* @group legacy
|
16 |
+
*/
|
17 |
public function testGetSource()
|
18 |
{
|
19 |
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
22 |
}
|
23 |
|
24 |
/**
|
25 |
+
* @group legacy
|
26 |
* @expectedException Twig_Error_Loader
|
27 |
*/
|
28 |
public function testGetSourceWhenTemplateDoesNotExist()
|
32 |
$loader->getSource('foo');
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @expectedException Twig_Error_Loader
|
37 |
+
*/
|
38 |
+
public function testGetSourceContextWhenTemplateDoesNotExist()
|
39 |
+
{
|
40 |
+
$loader = new Twig_Loader_Array(array());
|
41 |
+
|
42 |
+
$loader->getSourceContext('foo');
|
43 |
+
}
|
44 |
+
|
45 |
public function testGetCacheKey()
|
46 |
{
|
47 |
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
64 |
$loader = new Twig_Loader_Array(array());
|
65 |
$loader->setTemplate('foo', 'bar');
|
66 |
|
67 |
+
$this->assertEquals('bar', $loader->getSourceContext('foo')->getCode());
|
68 |
}
|
69 |
|
70 |
public function testIsFresh()
|
89 |
$loader = new Twig_Loader_Array(array('foo' => 'bar'));
|
90 |
|
91 |
$loader->getCacheKey($name);
|
92 |
+
$loader->getSourceContext($name);
|
93 |
$loader->isFresh($name, time());
|
94 |
$loader->setTemplate($name, 'foobar');
|
95 |
}
|
library/twig/twig/test/Twig/Tests/Loader/ChainTest.php
CHANGED
@@ -11,6 +11,9 @@
|
|
11 |
|
12 |
class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
|
|
|
|
|
|
14 |
public function testGetSource()
|
15 |
{
|
16 |
$loader = new Twig_Loader_Chain(array(
|
@@ -22,9 +25,41 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
|
|
22 |
$this->assertEquals('foo', $loader->getSource('bar'));
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
* @expectedException Twig_Error_Loader
|
27 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
public function testGetSourceWhenTemplateDoesNotExist()
|
29 |
{
|
30 |
$loader = new Twig_Loader_Chain(array());
|
@@ -58,17 +93,19 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
|
|
58 |
$loader = new Twig_Loader_Chain();
|
59 |
$loader->addLoader(new Twig_Loader_Array(array('foo' => 'bar')));
|
60 |
|
61 |
-
$this->assertEquals('bar', $loader->
|
62 |
}
|
63 |
|
64 |
public function testExists()
|
65 |
{
|
66 |
-
$loader1 = $this->getMockBuilder('Twig_Loader_Array')->setMethods(array('exists', '
|
67 |
$loader1->expects($this->once())->method('exists')->will($this->returnValue(false));
|
68 |
-
$loader1->expects($this->never())->method('
|
69 |
|
70 |
-
|
71 |
-
$loader2
|
|
|
|
|
72 |
|
73 |
$loader = new Twig_Loader_Chain();
|
74 |
$loader->addLoader($loader1);
|
@@ -77,3 +114,7 @@ class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
|
|
77 |
$this->assertTrue($loader->exists('foo'));
|
78 |
}
|
79 |
}
|
|
|
|
|
|
|
|
11 |
|
12 |
class Twig_Tests_Loader_ChainTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
+
/**
|
15 |
+
* @group legacy
|
16 |
+
*/
|
17 |
public function testGetSource()
|
18 |
{
|
19 |
$loader = new Twig_Loader_Chain(array(
|
25 |
$this->assertEquals('foo', $loader->getSource('bar'));
|
26 |
}
|
27 |
|
28 |
+
public function testGetSourceContext()
|
29 |
+
{
|
30 |
+
$path = dirname(__FILE__).'/../Fixtures';
|
31 |
+
$loader = new Twig_Loader_Chain(array(
|
32 |
+
new Twig_Loader_Array(array('foo' => 'bar')),
|
33 |
+
new Twig_Loader_Array(array('errors/index.html' => 'baz')),
|
34 |
+
new Twig_Loader_Filesystem(array($path)),
|
35 |
+
));
|
36 |
+
|
37 |
+
$this->assertEquals('foo', $loader->getSourceContext('foo')->getName());
|
38 |
+
$this->assertSame('', $loader->getSourceContext('foo')->getPath());
|
39 |
+
|
40 |
+
$this->assertEquals('errors/index.html', $loader->getSourceContext('errors/index.html')->getName());
|
41 |
+
$this->assertSame('', $loader->getSourceContext('errors/index.html')->getPath());
|
42 |
+
$this->assertEquals('baz', $loader->getSourceContext('errors/index.html')->getCode());
|
43 |
+
|
44 |
+
$this->assertEquals('errors/base.html', $loader->getSourceContext('errors/base.html')->getName());
|
45 |
+
$this->assertEquals(realpath($path.'/errors/base.html'), realpath($loader->getSourceContext('errors/base.html')->getPath()));
|
46 |
+
$this->assertNotEquals('baz', $loader->getSourceContext('errors/base.html')->getCode());
|
47 |
+
}
|
48 |
+
|
49 |
/**
|
50 |
* @expectedException Twig_Error_Loader
|
51 |
*/
|
52 |
+
public function testGetSourceContextWhenTemplateDoesNotExist()
|
53 |
+
{
|
54 |
+
$loader = new Twig_Loader_Chain(array());
|
55 |
+
|
56 |
+
$loader->getSourceContext('foo');
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @group legacy
|
61 |
+
* @expectedException Twig_Error_Loader
|
62 |
+
*/
|
63 |
public function testGetSourceWhenTemplateDoesNotExist()
|
64 |
{
|
65 |
$loader = new Twig_Loader_Chain(array());
|
93 |
$loader = new Twig_Loader_Chain();
|
94 |
$loader->addLoader(new Twig_Loader_Array(array('foo' => 'bar')));
|
95 |
|
96 |
+
$this->assertEquals('bar', $loader->getSourceContext('foo')->getCode());
|
97 |
}
|
98 |
|
99 |
public function testExists()
|
100 |
{
|
101 |
+
$loader1 = $this->getMockBuilder('Twig_Loader_Array')->setMethods(array('exists', 'getSourceContext'))->disableOriginalConstructor()->getMock();
|
102 |
$loader1->expects($this->once())->method('exists')->will($this->returnValue(false));
|
103 |
+
$loader1->expects($this->never())->method('getSourceContext');
|
104 |
|
105 |
+
// can be removed in 2.0
|
106 |
+
$loader2 = $this->getMockBuilder('Twig_ChainTestLoaderInterface')->getMock();
|
107 |
+
//$loader2 = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
|
108 |
+
$loader2->expects($this->once())->method('getSourceContext')->will($this->returnValue(new Twig_Source('content', 'index')));
|
109 |
|
110 |
$loader = new Twig_Loader_Chain();
|
111 |
$loader->addLoader($loader1);
|
114 |
$this->assertTrue($loader->exists('foo'));
|
115 |
}
|
116 |
}
|
117 |
+
|
118 |
+
interface Twig_ChainTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
|
119 |
+
{
|
120 |
+
}
|
library/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php
CHANGED
@@ -11,6 +11,14 @@
|
|
11 |
|
12 |
class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
/**
|
15 |
* @dataProvider getSecurityTests
|
16 |
*/
|
@@ -54,9 +62,9 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
54 |
/**
|
55 |
* @dataProvider getBasePaths
|
56 |
*/
|
57 |
-
public function testPaths($basePath)
|
58 |
{
|
59 |
-
$loader = new Twig_Loader_Filesystem(array($basePath.'/normal', $basePath.'/normal_bis'));
|
60 |
$loader->setPaths(array($basePath.'/named', $basePath.'/named_bis'), 'named');
|
61 |
$loader->addPath($basePath.'/named_ter', 'named');
|
62 |
$loader->addPath($basePath.'/normal_ter');
|
@@ -79,17 +87,40 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
79 |
), $loader->getPaths('named'));
|
80 |
|
81 |
// do not use realpath here as it would make the test unuseful
|
82 |
-
$this->assertEquals(
|
83 |
-
$this->assertEquals("path (final)\n", $loader->
|
84 |
-
$this->assertEquals("path (final)\n", $loader->
|
85 |
-
$this->assertEquals("named path (final)\n", $loader->
|
86 |
}
|
87 |
|
88 |
public function getBasePaths()
|
89 |
{
|
90 |
return array(
|
91 |
-
array(
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
);
|
94 |
}
|
95 |
|
@@ -116,7 +147,7 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
116 |
$loader->addPath($basePath.'/named', 'named');
|
117 |
|
118 |
try {
|
119 |
-
$loader->
|
120 |
} catch (Exception $e) {
|
121 |
$this->assertInstanceof('Twig_Error_Loader', $e);
|
122 |
$this->assertContains('Unable to find template "@named/nowhere.html"', $e->getMessage());
|
@@ -131,11 +162,11 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
131 |
$loader->addPath($basePath.'/named', 'named');
|
132 |
|
133 |
// prime the cache for index.html in the named namespace
|
134 |
-
$namedSource = $loader->
|
135 |
$this->assertEquals("named path\n", $namedSource);
|
136 |
|
137 |
// get index.html from the main namespace
|
138 |
-
$this->assertEquals("path\n", $loader->
|
139 |
}
|
140 |
|
141 |
public function testLoadTemplateAndRenderBlockWithCache()
|
@@ -179,4 +210,17 @@ class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
|
179 |
$template = $twig->loadTemplate($templateName);
|
180 |
$this->assertSame('VALID Child', $template->renderBlock('body', array()));
|
181 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
}
|
11 |
|
12 |
class Twig_Tests_Loader_FilesystemTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
+
public function testGetSourceContext()
|
15 |
+
{
|
16 |
+
$path = dirname(__FILE__).'/../Fixtures';
|
17 |
+
$loader = new Twig_Loader_Filesystem(array($path));
|
18 |
+
$this->assertEquals('errors/index.html', $loader->getSourceContext('errors/index.html')->getName());
|
19 |
+
$this->assertEquals(realpath($path.'/errors/index.html'), realpath($loader->getSourceContext('errors/index.html')->getPath()));
|
20 |
+
}
|
21 |
+
|
22 |
/**
|
23 |
* @dataProvider getSecurityTests
|
24 |
*/
|
62 |
/**
|
63 |
* @dataProvider getBasePaths
|
64 |
*/
|
65 |
+
public function testPaths($basePath, $cacheKey, $rootPath)
|
66 |
{
|
67 |
+
$loader = new Twig_Loader_Filesystem(array($basePath.'/normal', $basePath.'/normal_bis'), $rootPath);
|
68 |
$loader->setPaths(array($basePath.'/named', $basePath.'/named_bis'), 'named');
|
69 |
$loader->addPath($basePath.'/named_ter', 'named');
|
70 |
$loader->addPath($basePath.'/normal_ter');
|
87 |
), $loader->getPaths('named'));
|
88 |
|
89 |
// do not use realpath here as it would make the test unuseful
|
90 |
+
$this->assertEquals($cacheKey, str_replace('\\', '/', $loader->getCacheKey('@named/named_absolute.html')));
|
91 |
+
$this->assertEquals("path (final)\n", $loader->getSourceContext('index.html')->getCode());
|
92 |
+
$this->assertEquals("path (final)\n", $loader->getSourceContext('@__main__/index.html')->getCode());
|
93 |
+
$this->assertEquals("named path (final)\n", $loader->getSourceContext('@named/index.html')->getCode());
|
94 |
}
|
95 |
|
96 |
public function getBasePaths()
|
97 |
{
|
98 |
return array(
|
99 |
+
array(
|
100 |
+
dirname(__FILE__).'/Fixtures',
|
101 |
+
'test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html',
|
102 |
+
null,
|
103 |
+
),
|
104 |
+
array(
|
105 |
+
dirname(__FILE__).'/Fixtures/../Fixtures',
|
106 |
+
'test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html',
|
107 |
+
null,
|
108 |
+
),
|
109 |
+
array(
|
110 |
+
'test/Twig/Tests/Loader/Fixtures',
|
111 |
+
'test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html',
|
112 |
+
getcwd(),
|
113 |
+
),
|
114 |
+
array(
|
115 |
+
'Fixtures',
|
116 |
+
'Fixtures/named_quater/named_absolute.html',
|
117 |
+
getcwd().'/test/Twig/Tests/Loader',
|
118 |
+
),
|
119 |
+
array(
|
120 |
+
'Fixtures',
|
121 |
+
'Fixtures/named_quater/named_absolute.html',
|
122 |
+
getcwd().'/test/../test/Twig/Tests/Loader',
|
123 |
+
),
|
124 |
);
|
125 |
}
|
126 |
|
147 |
$loader->addPath($basePath.'/named', 'named');
|
148 |
|
149 |
try {
|
150 |
+
$loader->getSourceContext('@named/nowhere.html');
|
151 |
} catch (Exception $e) {
|
152 |
$this->assertInstanceof('Twig_Error_Loader', $e);
|
153 |
$this->assertContains('Unable to find template "@named/nowhere.html"', $e->getMessage());
|
162 |
$loader->addPath($basePath.'/named', 'named');
|
163 |
|
164 |
// prime the cache for index.html in the named namespace
|
165 |
+
$namedSource = $loader->getSourceContext('@named/index.html')->getCode();
|
166 |
$this->assertEquals("named path\n", $namedSource);
|
167 |
|
168 |
// get index.html from the main namespace
|
169 |
+
$this->assertEquals("path\n", $loader->getSourceContext('index.html')->getCode());
|
170 |
}
|
171 |
|
172 |
public function testLoadTemplateAndRenderBlockWithCache()
|
210 |
$template = $twig->loadTemplate($templateName);
|
211 |
$this->assertSame('VALID Child', $template->renderBlock('body', array()));
|
212 |
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* @requires PHP 5.3
|
216 |
+
*/
|
217 |
+
public function testLoadTemplateFromPhar()
|
218 |
+
{
|
219 |
+
$loader = new Twig_Loader_Filesystem(array());
|
220 |
+
// phar-sample.phar was created with the following script:
|
221 |
+
// $f = new Phar('phar-test.phar');
|
222 |
+
// $f->addFromString('hello.twig', 'hello from phar');
|
223 |
+
$loader->addPath('phar://'.dirname(__FILE__).'/Fixtures/phar/phar-sample.phar');
|
224 |
+
$this->assertSame('hello from phar', $loader->getSourceContext('hello.twig')->getCode());
|
225 |
+
}
|
226 |
}
|
library/twig/twig/test/Twig/Tests/Loader/Fixtures/phar/phar-sample.phar
ADDED
Binary file
|
library/twig/twig/test/Twig/Tests/NativeExtensionTest.php
CHANGED
@@ -11,6 +11,9 @@
|
|
11 |
|
12 |
class Twig_Tests_NativeExtensionTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
|
|
|
|
|
|
14 |
public function testGetProperties()
|
15 |
{
|
16 |
if (defined('HHVM_VERSION')) {
|
11 |
|
12 |
class Twig_Tests_NativeExtensionTest extends PHPUnit_Framework_TestCase
|
13 |
{
|
14 |
+
/**
|
15 |
+
* @requires PHP 5.3
|
16 |
+
*/
|
17 |
public function testGetProperties()
|
18 |
{
|
19 |
if (defined('HHVM_VERSION')) {
|
library/twig/twig/test/Twig/Tests/Node/Expression/NameTest.php
CHANGED
@@ -26,8 +26,16 @@ class Twig_Tests_Node_Expression_NameTest extends Twig_Test_NodeTestCase
|
|
26 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true));
|
27 |
$env1 = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => false));
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
return array(
|
30 |
-
array($node, "// line 1\n"
|
31 |
array($node, $this->getVariableGetter('foo', 1), $env1),
|
32 |
array($context, "// line 1\n\$context"),
|
33 |
);
|
26 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true));
|
27 |
$env1 = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => false));
|
28 |
|
29 |
+
if (PHP_VERSION_ID >= 70000) {
|
30 |
+
$output = '($context["foo"] ?? $this->getContext($context, "foo"))';
|
31 |
+
} elseif (PHP_VERSION_ID >= 50400) {
|
32 |
+
$output = '(isset($context["foo"]) ? $context["foo"] : $this->getContext($context, "foo"))';
|
33 |
+
} else {
|
34 |
+
$output = '$this->getContext($context, "foo")';
|
35 |
+
}
|
36 |
+
|
37 |
return array(
|
38 |
+
array($node, "// line 1\n".$output, $env),
|
39 |
array($node, $this->getVariableGetter('foo', 1), $env1),
|
40 |
array($context, "// line 1\n\$context"),
|
41 |
);
|
library/twig/twig/test/Twig/Tests/Node/Expression/NullCoalesceTest.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 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_Tests_Node_Expression_NullCoalesceTest extends Twig_Test_NodeTestCase
|
13 |
+
{
|
14 |
+
public function getTests()
|
15 |
+
{
|
16 |
+
$tests = array();
|
17 |
+
|
18 |
+
$left = new Twig_Node_Expression_Name('foo', 1);
|
19 |
+
$right = new Twig_Node_Expression_Constant(2, 1);
|
20 |
+
$node = new Twig_Node_Expression_NullCoalesce($left, $right, 1);
|
21 |
+
if (PHP_VERSION_ID >= 70000) {
|
22 |
+
$tests[] = array($node, "((// line 1\n\$context[\"foo\"]) ?? (2))");
|
23 |
+
} elseif (PHP_VERSION_ID >= 50400) {
|
24 |
+
$tests[] = array($node, "(((// line 1\narray_key_exists(\"foo\", \$context) && !(null === (isset(\$context[\"foo\"]) ? \$context[\"foo\"] : null)))) ? ((isset(\$context[\"foo\"]) ? \$context[\"foo\"] : null)) : (2))");
|
25 |
+
} else {
|
26 |
+
$tests[] = array($node, "(((// line 1\narray_key_exists(\"foo\", \$context) && !(null === \$this->getContext(\$context, \"foo\")))) ? (\$this->getContext(\$context, \"foo\")) : (2))");
|
27 |
+
}
|
28 |
+
|
29 |
+
return $tests;
|
30 |
+
}
|
31 |
+
}
|
library/twig/twig/test/Twig/Tests/Node/ModuleTest.php
CHANGED
@@ -18,14 +18,14 @@ class Twig_Tests_Node_ModuleTest extends Twig_Test_NodeTestCase
|
|
18 |
$blocks = new Twig_Node();
|
19 |
$macros = new Twig_Node();
|
20 |
$traits = new Twig_Node();
|
21 |
-
$
|
22 |
-
$node = new Twig_Node_Module($body, $parent, $blocks, $macros, $traits, new Twig_Node(array()), $
|
23 |
|
24 |
$this->assertEquals($body, $node->getNode('body'));
|
25 |
$this->assertEquals($blocks, $node->getNode('blocks'));
|
26 |
$this->assertEquals($macros, $node->getNode('macros'));
|
27 |
$this->assertEquals($parent, $node->getNode('parent'));
|
28 |
-
$this->assertEquals($
|
29 |
}
|
30 |
|
31 |
public function getTests()
|
@@ -39,9 +39,9 @@ class Twig_Tests_Node_ModuleTest extends Twig_Test_NodeTestCase
|
|
39 |
$blocks = new Twig_Node();
|
40 |
$macros = new Twig_Node();
|
41 |
$traits = new Twig_Node();
|
42 |
-
$
|
43 |
|
44 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $
|
45 |
$tests[] = array($node, <<<EOF
|
46 |
<?php
|
47 |
|
@@ -74,9 +74,17 @@ class __TwigTemplate_%x extends Twig_Template
|
|
74 |
return array ( 19 => 1,);
|
75 |
}
|
76 |
|
|
|
77 |
public function getSource()
|
78 |
{
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
}
|
81 |
}
|
82 |
EOF
|
@@ -87,7 +95,7 @@ EOF
|
|
87 |
$body = new Twig_Node(array($import));
|
88 |
$extends = new Twig_Node_Expression_Constant('layout.twig', 1);
|
89 |
|
90 |
-
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $
|
91 |
$tests[] = array($node, <<<EOF
|
92 |
<?php
|
93 |
|
@@ -132,9 +140,17 @@ class __TwigTemplate_%x extends Twig_Template
|
|
132 |
return array ( 26 => 1, 24 => 2, 11 => 1,);
|
133 |
}
|
134 |
|
|
|
135 |
public function getSource()
|
136 |
{
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
}
|
139 |
}
|
140 |
EOF
|
@@ -149,7 +165,8 @@ EOF
|
|
149 |
2
|
150 |
);
|
151 |
|
152 |
-
$
|
|
|
153 |
$tests[] = array($node, <<<EOF
|
154 |
<?php
|
155 |
|
@@ -185,9 +202,17 @@ class __TwigTemplate_%x extends Twig_Template
|
|
185 |
return array ( 17 => 2, 15 => 4, 9 => 2,);
|
186 |
}
|
187 |
|
|
|
188 |
public function getSource()
|
189 |
{
|
190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
}
|
192 |
}
|
193 |
EOF
|
18 |
$blocks = new Twig_Node();
|
19 |
$macros = new Twig_Node();
|
20 |
$traits = new Twig_Node();
|
21 |
+
$source = new Twig_Source('{{ foo }}', 'foo.twig');
|
22 |
+
$node = new Twig_Node_Module($body, $parent, $blocks, $macros, $traits, new Twig_Node(array()), $source);
|
23 |
|
24 |
$this->assertEquals($body, $node->getNode('body'));
|
25 |
$this->assertEquals($blocks, $node->getNode('blocks'));
|
26 |
$this->assertEquals($macros, $node->getNode('macros'));
|
27 |
$this->assertEquals($parent, $node->getNode('parent'));
|
28 |
+
$this->assertEquals($source->getName(), $node->getTemplateName());
|
29 |
}
|
30 |
|
31 |
public function getTests()
|
39 |
$blocks = new Twig_Node();
|
40 |
$macros = new Twig_Node();
|
41 |
$traits = new Twig_Node();
|
42 |
+
$source = new Twig_Source('{{ foo }}', 'foo.twig');
|
43 |
|
44 |
+
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $source);
|
45 |
$tests[] = array($node, <<<EOF
|
46 |
<?php
|
47 |
|
74 |
return array ( 19 => 1,);
|
75 |
}
|
76 |
|
77 |
+
/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */
|
78 |
public function getSource()
|
79 |
{
|
80 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);
|
81 |
+
|
82 |
+
return \$this->getSourceContext()->getCode();
|
83 |
+
}
|
84 |
+
|
85 |
+
public function getSourceContext()
|
86 |
+
{
|
87 |
+
return new Twig_Source("", "foo.twig", "");
|
88 |
}
|
89 |
}
|
90 |
EOF
|
95 |
$body = new Twig_Node(array($import));
|
96 |
$extends = new Twig_Node_Expression_Constant('layout.twig', 1);
|
97 |
|
98 |
+
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $source);
|
99 |
$tests[] = array($node, <<<EOF
|
100 |
<?php
|
101 |
|
140 |
return array ( 26 => 1, 24 => 2, 11 => 1,);
|
141 |
}
|
142 |
|
143 |
+
/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */
|
144 |
public function getSource()
|
145 |
{
|
146 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);
|
147 |
+
|
148 |
+
return \$this->getSourceContext()->getCode();
|
149 |
+
}
|
150 |
+
|
151 |
+
public function getSourceContext()
|
152 |
+
{
|
153 |
+
return new Twig_Source("", "foo.twig", "");
|
154 |
}
|
155 |
}
|
156 |
EOF
|
165 |
2
|
166 |
);
|
167 |
|
168 |
+
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('debug' => true));
|
169 |
+
$node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $source);
|
170 |
$tests[] = array($node, <<<EOF
|
171 |
<?php
|
172 |
|
202 |
return array ( 17 => 2, 15 => 4, 9 => 2,);
|
203 |
}
|
204 |
|
205 |
+
/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */
|
206 |
public function getSource()
|
207 |
{
|
208 |
+
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);
|
209 |
+
|
210 |
+
return \$this->getSourceContext()->getCode();
|
211 |
+
}
|
212 |
+
|
213 |
+
public function getSourceContext()
|
214 |
+
{
|
215 |
+
return new Twig_Source("{{ foo }}", "foo.twig", "");
|
216 |
}
|
217 |
}
|
218 |
EOF
|
library/twig/twig/test/Twig/Tests/Node/SandboxTest.php
CHANGED
@@ -28,7 +28,7 @@ class Twig_Tests_Node_SandboxTest extends Twig_Test_NodeTestCase
|
|
28 |
|
29 |
$tests[] = array($node, <<<EOF
|
30 |
// line 1
|
31 |
-
\$sandbox = \$this->env->getExtension('
|
32 |
if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {
|
33 |
\$sandbox->enableSandbox();
|
34 |
}
|
28 |
|
29 |
$tests[] = array($node, <<<EOF
|
30 |
// line 1
|
31 |
+
\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');
|
32 |
if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {
|
33 |
\$sandbox->enableSandbox();
|
34 |
}
|
library/twig/twig/test/Twig/Tests/Node/SandboxedPrintTest.php
CHANGED
@@ -24,7 +24,7 @@ class Twig_Tests_Node_SandboxedPrintTest extends Twig_Test_NodeTestCase
|
|
24 |
|
25 |
$tests[] = array(new Twig_Node_SandboxedPrint(new Twig_Node_Expression_Constant('foo', 1), 1), <<<EOF
|
26 |
// line 1
|
27 |
-
echo \$this->env->getExtension('
|
28 |
EOF
|
29 |
);
|
30 |
|
24 |
|
25 |
$tests[] = array(new Twig_Node_SandboxedPrint(new Twig_Node_Expression_Constant('foo', 1), 1), <<<EOF
|
26 |
// line 1
|
27 |
+
echo \$this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed("foo");
|
28 |
EOF
|
29 |
);
|
30 |
|
library/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php
CHANGED
@@ -14,7 +14,7 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
|
|
14 |
{
|
15 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
16 |
|
17 |
-
$stream = $env->parse($env->tokenize('{{ block("foo") }}', 'index'));
|
18 |
|
19 |
$node = $stream->getNode('body')->getNode(0);
|
20 |
|
@@ -26,7 +26,7 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
|
|
26 |
{
|
27 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
28 |
|
29 |
-
$stream = $env->parse($env->tokenize('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}', 'index'));
|
30 |
|
31 |
$node = $stream->getNode('blocks')->getNode('content')->getNode(0)->getNode('body');
|
32 |
|
@@ -41,7 +41,7 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
|
|
41 |
}
|
42 |
|
43 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
44 |
-
$stream = $env->parse($env->tokenize('{{ block(name|lower) }}', 'index'));
|
45 |
|
46 |
$node = $stream->getNode('body')->getNode(0)->getNode(1);
|
47 |
|
@@ -56,7 +56,7 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
|
|
56 |
{
|
57 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false));
|
58 |
|
59 |
-
$stream = $env->parse($env->tokenize($template, 'index'));
|
60 |
|
61 |
foreach ($expected as $target => $withLoop) {
|
62 |
$this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : ''));
|
14 |
{
|
15 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
16 |
|
17 |
+
$stream = $env->parse($env->tokenize(new Twig_Source('{{ block("foo") }}', 'index')));
|
18 |
|
19 |
$node = $stream->getNode('body')->getNode(0);
|
20 |
|
26 |
{
|
27 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
28 |
|
29 |
+
$stream = $env->parse($env->tokenize(new Twig_Source('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}', 'index')));
|
30 |
|
31 |
$node = $stream->getNode('blocks')->getNode('content')->getNode(0)->getNode('body');
|
32 |
|
41 |
}
|
42 |
|
43 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false));
|
44 |
+
$stream = $env->parse($env->tokenize(new Twig_Source('{{ block(name|lower) }}', 'index')));
|
45 |
|
46 |
$node = $stream->getNode('body')->getNode(0)->getNode(1);
|
47 |
|
56 |
{
|
57 |
$env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false));
|
58 |
|
59 |
+
$stream = $env->parse($env->tokenize(new Twig_Source($template, 'index')));
|
60 |
|
61 |
foreach ($expected as $target => $withLoop) {
|
62 |
$this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : ''));
|
library/twig/twig/test/Twig/Tests/ParserTest.php
CHANGED
@@ -100,7 +100,7 @@ class Twig_Tests_ParserTest extends PHPUnit_Framework_TestCase
|
|
100 |
|
101 |
/**
|
102 |
* @expectedException Twig_Error_Syntax
|
103 |
-
* @expectedExceptionMessage A template that extends another one cannot
|
104 |
*/
|
105 |
public function testFilterBodyNodesWithBOM()
|
106 |
{
|
@@ -141,14 +141,14 @@ class Twig_Tests_ParserTest extends PHPUnit_Framework_TestCase
|
|
141 |
'optimizations' => 0,
|
142 |
));
|
143 |
|
144 |
-
$twig->parse($twig->tokenize(<<<EOF
|
145 |
{% from _self import foo %}
|
146 |
|
147 |
{% macro foo() %}
|
148 |
{{ foo }}
|
149 |
{% endmacro %}
|
150 |
EOF
|
151 |
-
));
|
152 |
}
|
153 |
|
154 |
protected function getParser()
|
@@ -156,6 +156,7 @@ EOF
|
|
156 |
$parser = new TestParser(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
157 |
$parser->setParent(new Twig_Node());
|
158 |
$parser->stream = $this->getMockBuilder('Twig_TokenStream')->disableOriginalConstructor()->getMock();
|
|
|
159 |
|
160 |
return $parser;
|
161 |
}
|
100 |
|
101 |
/**
|
102 |
* @expectedException Twig_Error_Syntax
|
103 |
+
* @expectedExceptionMessage A template that extends another one cannot start with a byte order mark (BOM); it must be removed at line 1
|
104 |
*/
|
105 |
public function testFilterBodyNodesWithBOM()
|
106 |
{
|
141 |
'optimizations' => 0,
|
142 |
));
|
143 |
|
144 |
+
$twig->parse($twig->tokenize(new Twig_Source(<<<EOF
|
145 |
{% from _self import foo %}
|
146 |
|
147 |
{% macro foo() %}
|
148 |
{{ foo }}
|
149 |
{% endmacro %}
|
150 |
EOF
|
151 |
+
, 'index')));
|
152 |
}
|
153 |
|
154 |
protected function getParser()
|
156 |
$parser = new TestParser(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
157 |
$parser->setParent(new Twig_Node());
|
158 |
$parser->stream = $this->getMockBuilder('Twig_TokenStream')->disableOriginalConstructor()->getMock();
|
159 |
+
$parser->stream->expects($this->any())->method('getSourceContext')->will($this->returnValue(new Twig_Source('', '')));
|
160 |
|
161 |
return $parser;
|
162 |
}
|
library/twig/twig/test/Twig/Tests/TemplateTest.php
CHANGED
@@ -56,22 +56,22 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
56 |
public function getAttributeExceptions()
|
57 |
{
|
58 |
$tests = array(
|
59 |
-
array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1', false),
|
60 |
-
array('{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1', false),
|
61 |
-
array('{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1', false),
|
62 |
-
array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
|
63 |
-
array('{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1', false),
|
64 |
-
array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1', false),
|
65 |
-
array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1', false),
|
66 |
-
array('{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1', false),
|
67 |
-
array('{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1', false),
|
68 |
-
array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1', false),
|
69 |
-
array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1', false),
|
70 |
-
array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1', false),
|
71 |
-
array('{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1', false),
|
72 |
-
array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1', false),
|
73 |
array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.', false),
|
74 |
-
array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1', false),
|
75 |
);
|
76 |
|
77 |
if (function_exists('twig_template_get_attributes')) {
|
@@ -130,11 +130,16 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
130 |
|
131 |
/**
|
132 |
* @dataProvider getGetAttributeWithTemplateAsObject
|
|
|
133 |
*/
|
134 |
public function testGetAttributeWithTemplateAsObject($useExt)
|
135 |
{
|
136 |
-
|
137 |
-
$
|
|
|
|
|
|
|
|
|
138 |
|
139 |
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string'));
|
140 |
$this->assertEquals('some_string', $template->getAttribute($template1, 'string'));
|
@@ -167,6 +172,67 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
167 |
return $bools;
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
/**
|
171 |
* @dataProvider getTestsDependingOnExtensionAvailability
|
172 |
*/
|
@@ -279,6 +345,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
279 |
'null' => null,
|
280 |
'1' => 1,
|
281 |
'bar' => true,
|
|
|
282 |
'09' => '09',
|
283 |
'+4' => '+4',
|
284 |
);
|
@@ -307,6 +374,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
307 |
array(true, 1, 1.0),
|
308 |
array(true, null, 'null'),
|
309 |
array(true, true, 'bar'),
|
|
|
310 |
array(true, '09', '09'),
|
311 |
array(true, '+4', '+4'),
|
312 |
);
|
@@ -387,9 +455,9 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
387 |
|
388 |
// tests when input is not an array or object
|
389 |
$tests = array_merge($tests, array(
|
390 |
-
array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42")'),
|
391 |
-
array(false, null, 'string', 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a string variable ("string")'),
|
392 |
-
array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" does not exist as the array is empty'),
|
393 |
));
|
394 |
|
395 |
// add twig_template_get_attributes tests
|
@@ -409,12 +477,14 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
|
409 |
class Twig_TemplateTest extends Twig_Template
|
410 |
{
|
411 |
protected $useExtGetAttribute = false;
|
|
|
412 |
|
413 |
-
public function __construct(Twig_Environment $env, $useExtGetAttribute = false)
|
414 |
{
|
415 |
parent::__construct($env);
|
416 |
$this->useExtGetAttribute = $useExtGetAttribute;
|
417 |
self::$cache = array();
|
|
|
418 |
}
|
419 |
|
420 |
public function getZero()
|
@@ -439,6 +509,7 @@ class Twig_TemplateTest extends Twig_Template
|
|
439 |
|
440 |
public function getTemplateName()
|
441 |
{
|
|
|
442 |
}
|
443 |
|
444 |
public function getDebugInfo()
|
@@ -446,13 +517,9 @@ class Twig_TemplateTest extends Twig_Template
|
|
446 |
return array();
|
447 |
}
|
448 |
|
449 |
-
public function getSource()
|
450 |
-
{
|
451 |
-
return '';
|
452 |
-
}
|
453 |
-
|
454 |
protected function doGetParent(array $context)
|
455 |
{
|
|
|
456 |
}
|
457 |
|
458 |
protected function doDisplay(array $context, array $blocks = array())
|
@@ -479,6 +546,7 @@ class Twig_TemplateArrayAccessObject implements ArrayAccess
|
|
479 |
'null' => null,
|
480 |
'1' => 1,
|
481 |
'bar' => true,
|
|
|
482 |
'09' => '09',
|
483 |
'+4' => '+4',
|
484 |
);
|
@@ -511,6 +579,7 @@ class Twig_TemplateMagicPropertyObject
|
|
511 |
'null' => null,
|
512 |
'1' => 1,
|
513 |
'bar' => true,
|
|
|
514 |
'09' => '09',
|
515 |
'+4' => '+4',
|
516 |
);
|
@@ -542,6 +611,7 @@ class Twig_TemplatePropertyObject
|
|
542 |
public $zero = 0;
|
543 |
public $null = null;
|
544 |
public $bar = true;
|
|
|
545 |
|
546 |
protected $protected = 'protected';
|
547 |
}
|
@@ -618,6 +688,16 @@ class Twig_TemplateMethodObject
|
|
618 |
return true;
|
619 |
}
|
620 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
621 |
protected function getProtected()
|
622 |
{
|
623 |
return 'protected';
|
@@ -687,3 +767,8 @@ class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface
|
|
687 |
return 0;
|
688 |
}
|
689 |
}
|
|
|
|
|
|
|
|
|
|
56 |
public function getAttributeExceptions()
|
57 |
{
|
58 |
$tests = array(
|
59 |
+
array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1.', false),
|
60 |
+
array('{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1.', false),
|
61 |
+
array('{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.', false),
|
62 |
+
array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.', false),
|
63 |
+
array('{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1.', false),
|
64 |
+
array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1.', false),
|
65 |
+
array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1.', false),
|
66 |
+
array('{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1.', false),
|
67 |
+
array('{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1.', false),
|
68 |
+
array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.', false),
|
69 |
+
array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.', false),
|
70 |
+
array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1.', false),
|
71 |
+
array('{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.', false),
|
72 |
+
array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.', false),
|
73 |
array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.', false),
|
74 |
+
array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.', false),
|
75 |
);
|
76 |
|
77 |
if (function_exists('twig_template_get_attributes')) {
|
130 |
|
131 |
/**
|
132 |
* @dataProvider getGetAttributeWithTemplateAsObject
|
133 |
+
* @group legacy
|
134 |
*/
|
135 |
public function testGetAttributeWithTemplateAsObject($useExt)
|
136 |
{
|
137 |
+
// to be removed in 2.0
|
138 |
+
$twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock());
|
139 |
+
//$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface')->getMock());
|
140 |
+
|
141 |
+
$template = new Twig_TemplateTest($twig, $useExt, 'index.twig');
|
142 |
+
$template1 = new Twig_TemplateTest($twig, false, 'index1.twig');
|
143 |
|
144 |
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string'));
|
145 |
$this->assertEquals('some_string', $template->getAttribute($template1, 'string'));
|
172 |
return $bools;
|
173 |
}
|
174 |
|
175 |
+
/**
|
176 |
+
* @group legacy
|
177 |
+
* @expectedDeprecation Calling "getString" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
178 |
+
* @expectedDeprecation Calling "getString" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
179 |
+
* @expectedDeprecation Calling "getTrue" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
180 |
+
* @expectedDeprecation Calling "getTrue" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
181 |
+
* @expectedDeprecation Calling "getZero" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
182 |
+
* @expectedDeprecation Calling "getZero" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
183 |
+
* @expectedDeprecation Calling "getEmpty" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
184 |
+
* @expectedDeprecation Calling "getEmpty" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
|
185 |
+
* @expectedDeprecation Calling "renderBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name") instead).
|
186 |
+
* @expectedDeprecation Calling "displayBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name") instead).
|
187 |
+
* @expectedDeprecation Calling "hasBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use "block("name") is defined" instead).
|
188 |
+
* @expectedDeprecation Calling "render" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index.twig") instead).
|
189 |
+
* @expectedDeprecation Calling "display" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index.twig") instead).
|
190 |
+
* @expectedDeprecation Calling "renderBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name", template) instead).
|
191 |
+
* @expectedDeprecation Calling "displayBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name", template) instead).
|
192 |
+
* @expectedDeprecation Calling "hasBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use "block("name", template) is defined" instead).
|
193 |
+
* @expectedDeprecation Calling "render" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index1.twig") instead).
|
194 |
+
* @expectedDeprecation Calling "display" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index1.twig") instead).
|
195 |
+
*/
|
196 |
+
public function testGetAttributeWithTemplateAsObjectForDeprecations()
|
197 |
+
{
|
198 |
+
// to be removed in 2.0
|
199 |
+
$twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock());
|
200 |
+
//$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface')->getMock());
|
201 |
+
|
202 |
+
$template = new Twig_TemplateTest($twig, false, 'index.twig');
|
203 |
+
$template1 = new Twig_TemplateTest($twig, false, 'index1.twig');
|
204 |
+
|
205 |
+
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string'));
|
206 |
+
$this->assertEquals('some_string', $template->getAttribute($template1, 'string'));
|
207 |
+
|
208 |
+
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'true'));
|
209 |
+
$this->assertEquals('1', $template->getAttribute($template1, 'true'));
|
210 |
+
|
211 |
+
$this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'zero'));
|
212 |
+
$this->assertEquals('0', $template->getAttribute($template1, 'zero'));
|
213 |
+
|
214 |
+
$this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty'));
|
215 |
+
$this->assertSame('', $template->getAttribute($template1, 'empty'));
|
216 |
+
|
217 |
+
// trigger some deprecation notice messages to check them with @expectedDeprecation
|
218 |
+
$template->getAttribute($template, 'renderBlock', array('name', array()));
|
219 |
+
$template->getAttribute($template, 'displayBlock', array('name', array()));
|
220 |
+
$template->getAttribute($template, 'hasBlock', array('name', array()));
|
221 |
+
$template->getAttribute($template, 'render', array(array()));
|
222 |
+
$template->getAttribute($template, 'display', array(array()));
|
223 |
+
|
224 |
+
$template->getAttribute($template1, 'renderBlock', array('name', array()));
|
225 |
+
$template->getAttribute($template1, 'displayBlock', array('name', array()));
|
226 |
+
$template->getAttribute($template1, 'hasBlock', array('name', array()));
|
227 |
+
$template->getAttribute($template1, 'render', array(array()));
|
228 |
+
$template->getAttribute($template1, 'display', array(array()));
|
229 |
+
|
230 |
+
$this->assertFalse($template->getAttribute($template1, 'env', array(), Twig_Template::ANY_CALL, true));
|
231 |
+
$this->assertFalse($template->getAttribute($template1, 'environment', array(), Twig_Template::ANY_CALL, true));
|
232 |
+
$this->assertFalse($template->getAttribute($template1, 'getEnvironment', array(), Twig_Template::METHOD_CALL, true));
|
233 |
+
$this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true));
|
234 |
+
}
|
235 |
+
|
236 |
/**
|
237 |
* @dataProvider getTestsDependingOnExtensionAvailability
|
238 |
*/
|
345 |
'null' => null,
|
346 |
'1' => 1,
|
347 |
'bar' => true,
|
348 |
+
'baz' => 'baz',
|
349 |
'09' => '09',
|
350 |
'+4' => '+4',
|
351 |
);
|
374 |
array(true, 1, 1.0),
|
375 |
array(true, null, 'null'),
|
376 |
array(true, true, 'bar'),
|
377 |
+
array(true, 'baz', 'baz'),
|
378 |
array(true, '09', '09'),
|
379 |
array(true, '+4', '+4'),
|
380 |
);
|
455 |
|
456 |
// tests when input is not an array or object
|
457 |
$tests = array_merge($tests, array(
|
458 |
+
array(false, null, 42, 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a integer variable ("42") in "index.twig".'),
|
459 |
+
array(false, null, 'string', 'a', array(), $anyType, false, 'Impossible to access an attribute ("a") on a string variable ("string") in "index.twig".'),
|
460 |
+
array(false, null, array(), 'a', array(), $anyType, false, 'Key "a" does not exist as the array is empty in "index.twig".'),
|
461 |
));
|
462 |
|
463 |
// add twig_template_get_attributes tests
|
477 |
class Twig_TemplateTest extends Twig_Template
|
478 |
{
|
479 |
protected $useExtGetAttribute = false;
|
480 |
+
private $name;
|
481 |
|
482 |
+
public function __construct(Twig_Environment $env, $useExtGetAttribute = false, $name = 'index.twig')
|
483 |
{
|
484 |
parent::__construct($env);
|
485 |
$this->useExtGetAttribute = $useExtGetAttribute;
|
486 |
self::$cache = array();
|
487 |
+
$this->name = $name;
|
488 |
}
|
489 |
|
490 |
public function getZero()
|
509 |
|
510 |
public function getTemplateName()
|
511 |
{
|
512 |
+
return $this->name;
|
513 |
}
|
514 |
|
515 |
public function getDebugInfo()
|
517 |
return array();
|
518 |
}
|
519 |
|
|
|
|
|
|
|
|
|
|
|
520 |
protected function doGetParent(array $context)
|
521 |
{
|
522 |
+
return false;
|
523 |
}
|
524 |
|
525 |
protected function doDisplay(array $context, array $blocks = array())
|
546 |
'null' => null,
|
547 |
'1' => 1,
|
548 |
'bar' => true,
|
549 |
+
'baz' => 'baz',
|
550 |
'09' => '09',
|
551 |
'+4' => '+4',
|
552 |
);
|
579 |
'null' => null,
|
580 |
'1' => 1,
|
581 |
'bar' => true,
|
582 |
+
'baz' => 'baz',
|
583 |
'09' => '09',
|
584 |
'+4' => '+4',
|
585 |
);
|
611 |
public $zero = 0;
|
612 |
public $null = null;
|
613 |
public $bar = true;
|
614 |
+
public $baz = 'baz';
|
615 |
|
616 |
protected $protected = 'protected';
|
617 |
}
|
688 |
return true;
|
689 |
}
|
690 |
|
691 |
+
public function isBaz()
|
692 |
+
{
|
693 |
+
return 'should never be returned';
|
694 |
+
}
|
695 |
+
|
696 |
+
public function getBaz()
|
697 |
+
{
|
698 |
+
return 'baz';
|
699 |
+
}
|
700 |
+
|
701 |
protected function getProtected()
|
702 |
{
|
703 |
return 'protected';
|
767 |
return 0;
|
768 |
}
|
769 |
}
|
770 |
+
|
771 |
+
// to be removed in 2.0
|
772 |
+
interface Twig_TemplateTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
|
773 |
+
{
|
774 |
+
}
|
library/twig/twig/test/Twig/Tests/TemplateWrapperTest.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Twig.
|
5 |
+
*
|
6 |
+
* (c) 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_Tests_TemplateWrapperTest extends PHPUnit_Framework_TestCase
|
12 |
+
{
|
13 |
+
public function testHasGetBlocks()
|
14 |
+
{
|
15 |
+
$twig = new Twig_Environment(new Twig_Loader_Array(array(
|
16 |
+
'index' => '{% block foo %}{% endblock %}',
|
17 |
+
'index_with_use' => '{% use "imported" %}{% block foo %}{% endblock %}',
|
18 |
+
'index_with_extends' => '{% extends "extended" %}{% block foo %}{% endblock %}',
|
19 |
+
'imported' => '{% block imported %}{% endblock %}',
|
20 |
+
'extended' => '{% block extended %}{% endblock %}',
|
21 |
+
)));
|
22 |
+
|
23 |
+
$wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index'));
|
24 |
+
$this->assertTrue($wrapper->hasBlock('foo'));
|
25 |
+
$this->assertFalse($wrapper->hasBlock('bar'));
|
26 |
+
$this->assertEquals(array('foo'), $wrapper->getBlockNames());
|
27 |
+
|
28 |
+
$wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index_with_use'));
|
29 |
+
$this->assertTrue($wrapper->hasBlock('foo'));
|
30 |
+
$this->assertTrue($wrapper->hasBlock('imported'));
|
31 |
+
$this->assertEquals(array('imported', 'foo'), $wrapper->getBlockNames());
|
32 |
+
|
33 |
+
$wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index_with_extends'));
|
34 |
+
$this->assertTrue($wrapper->hasBlock('foo'));
|
35 |
+
$this->assertTrue($wrapper->hasBlock('extended'));
|
36 |
+
$this->assertEquals(array('foo', 'extended'), $wrapper->getBlockNames());
|
37 |
+
}
|
38 |
+
|
39 |
+
public function testRenderBlock()
|
40 |
+
{
|
41 |
+
$twig = new Twig_Environment(new Twig_Loader_Array(array(
|
42 |
+
'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}',
|
43 |
+
)));
|
44 |
+
$twig->addGlobal('bar', 'BAR');
|
45 |
+
|
46 |
+
$wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index'));
|
47 |
+
$this->assertEquals('FOOBAR', $wrapper->renderBlock('foo', array('foo' => 'FOO')));
|
48 |
+
}
|
49 |
+
|
50 |
+
public function testDisplayBlock()
|
51 |
+
{
|
52 |
+
$twig = new Twig_Environment(new Twig_Loader_Array(array(
|
53 |
+
'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}',
|
54 |
+
)));
|
55 |
+
$twig->addGlobal('bar', 'BAR');
|
56 |
+
|
57 |
+
$wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index'));
|
58 |
+
|
59 |
+
ob_start();
|
60 |
+
$wrapper->displayBlock('foo', array('foo' => 'FOO'));
|
61 |
+
|
62 |
+
$this->assertEquals('FOOBAR', ob_get_clean());
|
63 |
+
}
|
64 |
+
}
|
library/twig/twig/test/Twig/Tests/TokenStreamTest.php
CHANGED
@@ -27,6 +27,18 @@ class Twig_Tests_TokenStreamTest extends PHPUnit_Framework_TestCase
|
|
27 |
);
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
public function testNext()
|
31 |
{
|
32 |
$stream = new Twig_TokenStream(self::$tokens);
|
27 |
);
|
28 |
}
|
29 |
|
30 |
+
/**
|
31 |
+
* @group legacy
|
32 |
+
*/
|
33 |
+
public function testLegacyConstructorSignature()
|
34 |
+
{
|
35 |
+
$stream = new Twig_TokenStream(array(), 'foo', '{{ foo }}');
|
36 |
+
$this->assertEquals('foo', $stream->getFilename());
|
37 |
+
$this->assertEquals('{{ foo }}', $stream->getSource());
|
38 |
+
$this->assertEquals('foo', $stream->getSourceContext()->getName());
|
39 |
+
$this->assertEquals('{{ foo }}', $stream->getSourceContext()->getCode());
|
40 |
+
}
|
41 |
+
|
42 |
public function testNext()
|
43 |
{
|
44 |
$stream = new Twig_TokenStream(self::$tokens);
|
library/twig/twig/test/Twig/Tests/escapingTest.php
CHANGED
@@ -250,7 +250,7 @@ class Twig_Test_EscapingTest extends PHPUnit_Framework_TestCase
|
|
250 |
.chr($codepoint >> 6 & 0x3f | 0x80)
|
251 |
.chr($codepoint & 0x3f | 0x80);
|
252 |
}
|
253 |
-
throw new Exception('Codepoint requested outside of Unicode range');
|
254 |
}
|
255 |
|
256 |
public function testJavascriptEscapingEscapesOwaspRecommendedRanges()
|
250 |
.chr($codepoint >> 6 & 0x3f | 0x80)
|
251 |
.chr($codepoint & 0x3f | 0x80);
|
252 |
}
|
253 |
+
throw new Exception('Codepoint requested outside of Unicode range.');
|
254 |
}
|
255 |
|
256 |
public function testJavascriptEscapingEscapesOwaspRecommendedRanges()
|
readme.txt
CHANGED
@@ -6,21 +6,30 @@ Text Domain: wpcf
|
|
6 |
Domain Path: /embedded/locale
|
7 |
License: GPLv2
|
8 |
Requires at least: 3.7
|
9 |
-
Tested up to: 4.
|
10 |
-
Stable tag: 2.2.
|
11 |
|
12 |
The complete and reliable plugin for managing custom post types, custom taxonomies and custom fields.
|
13 |
|
14 |
== Description ==
|
15 |
|
16 |
-
Types let's you customize the WordPress admin by adding content types, custom fields and taxonomies. You will be able to craft the WordPress admin and turn it into your very own content management system
|
17 |
|
18 |
[vimeo https://vimeo.com/176428571]
|
19 |
|
20 |
-
= POWERFUL
|
21 |
-
If you're an experienced PHP developer, you'll appreciate Types comprehensive [
|
22 |
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
= CUSTOM FIELDS FOR CONTENT AND USERS =
|
26 |
Types lets you add custom fields for both posts (meaning, WordPress posts, pages and custom content types), as well as users. You can add any field types to different user profiles.
|
@@ -98,7 +107,7 @@ By default, WordPress will either display your blog posts or a specific page on
|
|
98 |
To display custom post types on the home-page, you have two options:
|
99 |
|
100 |
1. If you're comfortable with PHP and WordPress API, edit the site's template files (probably index.php) and load the custom post types there. Different themes do this differently, so we can't really say what single approach works best. You should look at [get_posts](http://codex.wordpress.org/Template_Tags/get_posts), which is part of the WordPress Template Tags system.
|
101 |
-
2. If you want to build sites right away, without becoming an expert in WordPress API and try our [Views
|
102 |
|
103 |
We're sorry, but we don't know of any third option which is both free and requires no coding.
|
104 |
|
@@ -151,6 +160,21 @@ Additionally, Types is the only plugin that lets you define parent/child relatio
|
|
151 |
|
152 |
== Changelog ==
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
= 2.2.3 =
|
155 |
* Fixed several security issues.
|
156 |
|
6 |
Domain Path: /embedded/locale
|
7 |
License: GPLv2
|
8 |
Requires at least: 3.7
|
9 |
+
Tested up to: 4.7
|
10 |
+
Stable tag: 2.2.4
|
11 |
|
12 |
The complete and reliable plugin for managing custom post types, custom taxonomies and custom fields.
|
13 |
|
14 |
== Description ==
|
15 |
|
16 |
+
**Types let's you customize the WordPress admin by adding content types, custom fields and taxonomies. You will be able to craft the WordPress admin and turn it into your very own content management system.**
|
17 |
|
18 |
[vimeo https://vimeo.com/176428571]
|
19 |
|
20 |
+
= COMPLETE DOCUMENTATION, POWERFUL API, SIMPLE GUI FOR NON-CODERS =
|
21 |
+
If you're an experienced PHP developer, you'll appreciate Types comprehensive [fields API](http://wp-types.com/documentation/functions/).
|
22 |
|
23 |
+
You will find detailed guides on [adding custom post types, fields and taxonomy to the front-end](https://wp-types.com/documentation/customizing-sites-using-php/), including:
|
24 |
+
|
25 |
+
* [Creating templates for single custom posts](https://wp-types.com/documentation/customizing-sites-using-php/creating-templates-single-custom-posts)
|
26 |
+
* [Creating templates for custom post type archives](https://wp-types.com/documentation/customizing-sites-using-php/creating-templates-custom-post-type-archives)
|
27 |
+
* [Creating custom user profiles](https://wp-types.com/documentation/customizing-sites-using-php/creating-custom-user-profiles)
|
28 |
+
* [Create taxonomy term archives](https://wp-types.com/documentation/customizing-sites-using-php/creating-taxonomy-term-archives)
|
29 |
+
|
30 |
+
and [more](https://wp-types.com/documentation/customizing-sites-using-php/).
|
31 |
+
|
32 |
+
**Too much technical stuff to learn?** The full [Toolset](http://wp-types.com) package lets you build complete WordPress sites from within the admin dashboard.
|
33 |
|
34 |
= CUSTOM FIELDS FOR CONTENT AND USERS =
|
35 |
Types lets you add custom fields for both posts (meaning, WordPress posts, pages and custom content types), as well as users. You can add any field types to different user profiles.
|
107 |
To display custom post types on the home-page, you have two options:
|
108 |
|
109 |
1. If you're comfortable with PHP and WordPress API, edit the site's template files (probably index.php) and load the custom post types there. Different themes do this differently, so we can't really say what single approach works best. You should look at [get_posts](http://codex.wordpress.org/Template_Tags/get_posts), which is part of the WordPress Template Tags system.
|
110 |
+
2. If you want to build sites right away, without becoming an expert in WordPress API and try our [Toolset Views](http://wp-types.com/). You'll be able to load whatever content you need from the database and display it anywhere and in whatever way you choose.
|
111 |
|
112 |
We're sorry, but we don't know of any third option which is both free and requires no coding.
|
113 |
|
160 |
|
161 |
== Changelog ==
|
162 |
|
163 |
+
= 2.2.4 =
|
164 |
+
|
165 |
+
* Fix an issue with registering custom taxonomies in WordPress 4.7.
|
166 |
+
* Implement an alternative escaping mechanism for custom format setting of the date field.
|
167 |
+
* types_render_shortcode() function and [types] shortcode now allows to use "id" attribute for $parent-post selection
|
168 |
+
* Exclude Media from post relationships since the current GUI isn't able to support it properly
|
169 |
+
* Fix exporting taxonomies with legacy "object_type" setting that was causing syntax errors in the output XML.
|
170 |
+
* Support all CPTs in Toolset Dashboard.
|
171 |
+
* Change the way we store the context of a Types field for string translation (use field group name instead of ID)
|
172 |
+
* Fix a WordPress 4.7 compatibility issue with direct access to $wp_filter.
|
173 |
+
* Make the manipulation with repetitive user field values more similar to post fields. Fix a front-end notice when there is only one value in a repeating user Skype field.
|
174 |
+
* Add missing mandatory URL validation to file fields.
|
175 |
+
* Add PHP template example files.
|
176 |
+
* Fix an issue with Types export and non-latin characters in a field group slug.
|
177 |
+
|
178 |
= 2.2.3 =
|
179 |
* Fixed several security issues.
|
180 |
|
wpcf.php
CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://wordpress.org/extend/plugins/types/
|
|
5 |
Description: Toolset Types defines custom content in WordPress. Easily create custom post types, fields and taxonomy and connect everything together.
|
6 |
Author: OnTheGoSystems
|
7 |
Author URI: http://www.onthegosystems.com
|
8 |
-
Version: 2.2.
|
9 |
License: GPLv2 or later
|
10 |
|
11 |
Types is free software: you can redistribute it and/or modify
|
@@ -28,7 +28,7 @@ if( !function_exists( 'add_action' ) )
|
|
28 |
|
29 |
// version
|
30 |
if( ! defined( 'TYPES_VERSION' ) )
|
31 |
-
define( 'TYPES_VERSION', '2.2.
|
32 |
|
33 |
// backward compatibility
|
34 |
if ( ! defined( 'WPCF_VERSION' ) )
|
@@ -36,7 +36,8 @@ if ( ! defined( 'WPCF_VERSION' ) )
|
|
36 |
|
37 |
// release notes
|
38 |
if( ! defined( 'TYPES_RELEASE_NOTES' ) )
|
39 |
-
|
|
|
40 |
|
41 |
/*
|
42 |
* Path Constants
|
5 |
Description: Toolset Types defines custom content in WordPress. Easily create custom post types, fields and taxonomy and connect everything together.
|
6 |
Author: OnTheGoSystems
|
7 |
Author URI: http://www.onthegosystems.com
|
8 |
+
Version: 2.2.4
|
9 |
License: GPLv2 or later
|
10 |
|
11 |
Types is free software: you can redistribute it and/or modify
|
28 |
|
29 |
// version
|
30 |
if( ! defined( 'TYPES_VERSION' ) )
|
31 |
+
define( 'TYPES_VERSION', '2.2.4' );
|
32 |
|
33 |
// backward compatibility
|
34 |
if ( ! defined( 'WPCF_VERSION' ) )
|
36 |
|
37 |
// release notes
|
38 |
if( ! defined( 'TYPES_RELEASE_NOTES' ) )
|
39 |
+
// Mind the end of the URL string, it contains the plugin version.
|
40 |
+
define( 'TYPES_RELEASE_NOTES', 'https://wp-types.com/version/types-2-2-4/?utm_source=typesplugin&utm_campaign=types&utm_medium=release-notes-admin-notice&utm_term=Types%202.2.4%20release%20notes' );
|
41 |
|
42 |
/*
|
43 |
* Path Constants
|