Merge remote-tracking branch 'phpbb/develop' into ticket/9657

* phpbb/develop: (216 commits)
  [ticket/11626] Remove last reference to template in ldap
  [ticket/11626] Remove LDAP dependency on template
  [develop-olympus] Increment version number to 3.0.13-dev.
  [develop-olympus] Add changelog for 3.0.12 release.
  [develop-olympus] Bump version numbers for 3.0.12-RC1 release.
  [develop-olympus] Bumping version numbers to final for 3.0.12 releases.
  [ticket/11669] Fix PHP bug #55124 (recursive mkdir on /./)
  [ticket/11668] Run lint test at the end of the test suite
  [ticket/11548] Fix test errors in groups test on develop
  [ticket/11548] Check upload avatar URL the same way as in phpBB 3.0
  [ticket/11548] Fix incorrect usage of array_map on acp groups page
  [ticket/11665] Fix test class name
  [ticket/11664] Stop creating php.html file in root path in tests
  [ticket/11665] Can't change file names already sent to set_filenames
  [ticket/11662] Typos: occured -> occurred
  [ticket/11662] Typos: occured -> occurred
  [ticket/11660] Fix bugs from bugs in #11651 (missing vars, db->sql_connect)
  [feature/auth-refactor] Add parent::setUp() in setUp()
  [feature/auth-refactor] Changes
  [feature/auth-refactor] DataProvider for acp_board test
  ...
This commit is contained in:
Joas Schilling 2013-07-13 09:36:24 -04:00
commit 8352a7cada
122 changed files with 3601 additions and 2825 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
*~
/phpunit.xml
/phpBB/cache/twig/*
/phpBB/cache/*.html
/phpBB/cache/*.php
/phpBB/cache/*.lock

View file

@ -34,7 +34,7 @@
<!-- IF S_AUTH -->
<!-- BEGIN auth_tpl -->
{auth_tpl.TPL}
<!-- INCLUDE {auth_tpl.TEMPLATE_FILE} -->
<!-- END auth_tpl -->
<!-- ENDIF -->

View file

@ -437,7 +437,7 @@
</div>
<!-- ENDIF -->
<p><strong>{NAVIGATION}<!-- IF S_NO_FORUMS --> [<a href="{U_EDIT}">{L_EDIT}</a> | <a href="{U_DELETE}">{L_DELETE}</a><!-- IF not S_LINK --> | <a href="{U_SYNC}">{L_RESYNC}</a><!-- ENDIF --->]<!-- ENDIF --></strong></p>
<p><strong>{NAVIGATION}<!-- IF S_NO_FORUMS --> [<a href="{U_EDIT}">{L_EDIT}</a> | <a href="{U_DELETE}">{L_DELETE}</a><!-- IF not S_LINK --> | <a href="{U_SYNC}">{L_RESYNC}</a><!-- ENDIF -->]<!-- ENDIF --></strong></p>
<!-- IF .forums -->
<table cellspacing="1">

View file

@ -0,0 +1,32 @@
<dl>
<dt><label for="ldap_server">{L_LDAP_SERVER}{L_COLON}</label><br /><span>{L_LDAP_SERVER_EXPLAIN}</span></dt>
<dd><input type="text" id="ldap_server" size="40" name="config[ldap_server]" value="{AUTH_LDAP_SERVER}" /></dd>
</dl>
<dl>
<dt><label for="ldap_port">{L_LDAP_PORT}{L_COLON}</label><br /><span>{L_LDAP_PORT_EXPLAIN}</span></dt>
<dd><input type="text" id="ldap_port" size="40" name="config[ldap_port]" value="{AUTH_LDAP_PORT}" /></dd>
</dl>
<dl>
<dt><label for="ldap_dn">{L_LDAP_DN}{L_COLON}</label><br /><span>{L_LDAP_DN_EXPLAIN}</span></dt>
<dd><input type="text" id="ldap_dn" size="40" name="config[ldap_base_dn]" value="{AUTH_LDAP_BASE_DN}" /></dd>
</dl>
<dl>
<dt><label for="ldap_uid">{L_LDAP_UID}{L_COLON}</label><br /><span>{L_LDAP_UID_EXPLAIN}</span></dt>
<dd><input type="text" id="ldap_uid" size="40" name="config[ldap_uid]" value="{AUTH_LDAP_UID}" /></dd>
</dl>
<dl>
<dt><label for="ldap_user_filter">{L_LDAP_USER_FILTER}{L_COLON}</label><br /><span>{L_LDAP_USER_FILTER_EXPLAIN}</span></dt>
<dd><input type="text" id="ldap_user_filter" size="40" name="config[ldap_user_filter]" value="{AUTH_LDAP_USER_FILTER}" /></dd>
</dl>
<dl>
<dt><label for="ldap_email">{L_LDAP_EMAIL}{L_COLON}</label><br /><span>{L_LDAP_EMAIL_EXPLAIN}</span></dt>
<dd><input type="email" id="ldap_email" size="40" name="config[ldap_email]" value="{AUTH_LDAP_EMAIL}" /></dd>
</dl>
<dl>
<dt><label for="ldap_user">{L_LDAP_USER}{L_COLON}</label><br /><span>{L_LDAP_USER_EXPLAIN}</span></dt>
<dd><input type="text" id="ldap_user" size="40" name="config[ldap_user]" value="{AUTH_LDAP_USER}" /></dd>
</dl>
<dl>
<dt><label for="ldap_password">{L_LDAP_PASSWORD}{L_COLON}</label><br /><span>{L_LDAP_PASSWORD_EXPLAIN}</span></dt>
<dd><input type="password" id="ldap_password" size="40" name="config[ldap_password]" value="{AUTH_LDAP_PASSWORD}" autocomplete="off" /></dd>
</dl>

View file

@ -6,7 +6,8 @@
"symfony/event-dispatcher": "2.1.*",
"symfony/http-kernel": "2.1.*",
"symfony/routing": "2.1.*",
"symfony/yaml": "2.1.*"
"symfony/yaml": "2.1.*",
"twig/twig": "1.13.*"
},
"require-dev": {
"fabpot/goutte": "v0.1.0",

196
phpBB/composer.lock generated
View file

@ -3,21 +3,21 @@
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
],
"hash": "3792dc25490f24210ece3b40789c5b98",
"hash": "e4a4f4848a7201d7e044446001afda29",
"packages": [
{
"name": "symfony/config",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/Config",
"source": {
"type": "git",
"url": "https://github.com/symfony/Config.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Config/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/Config/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -29,7 +29,6 @@
"Symfony\\Component\\Config": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -45,21 +44,21 @@
],
"description": "Symfony Config Component",
"homepage": "http://symfony.com",
"time": "2013-04-22 04:28:40"
"time": "2013-05-09 15:22:40"
},
{
"name": "symfony/dependency-injection",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/DependencyInjection",
"source": {
"type": "git",
"url": "https://github.com/symfony/DependencyInjection.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -79,7 +78,6 @@
"Symfony\\Component\\DependencyInjection": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -99,17 +97,17 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/EventDispatcher",
"source": {
"type": "git",
"url": "https://github.com/symfony/EventDispatcher.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -128,7 +126,6 @@
"Symfony\\Component\\EventDispatcher": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -148,17 +145,17 @@
},
{
"name": "symfony/http-foundation",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/HttpFoundation",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpFoundation.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -171,7 +168,6 @@
"SessionHandlerInterface": "Symfony/Component/HttpFoundation/Resources/stubs"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -187,21 +183,21 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "http://symfony.com",
"time": "2013-04-30 17:01:33"
"time": "2013-05-26 18:42:07"
},
{
"name": "symfony/http-kernel",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/HttpKernel",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpKernel.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -233,7 +229,6 @@
"Symfony\\Component\\HttpKernel": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -249,21 +244,21 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "http://symfony.com",
"time": "2013-05-06 11:01:51"
"time": "2013-06-02 12:29:05"
},
{
"name": "symfony/routing",
"version": "v2.1.9",
"version": "v2.1.11",
"target-dir": "Symfony/Component/Routing",
"source": {
"type": "git",
"url": "https://github.com/symfony/Routing.git",
"reference": "v2.1.9"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Routing/zipball/v2.1.9",
"reference": "v2.1.9",
"url": "https://api.github.com/repos/symfony/Routing/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -286,7 +281,6 @@
"Symfony\\Component\\Routing": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -302,21 +296,21 @@
],
"description": "Symfony Routing Component",
"homepage": "http://symfony.com",
"time": "2013-03-23 07:47:35"
"time": "2013-05-06 10:48:41"
},
{
"name": "symfony/yaml",
"version": "v2.1.9",
"version": "v2.1.11",
"target-dir": "Symfony/Component/Yaml",
"source": {
"type": "git",
"url": "https://github.com/symfony/Yaml.git",
"reference": "v2.1.9"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.1.9",
"reference": "v2.1.9",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -328,7 +322,6 @@
"Symfony\\Component\\Yaml": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -344,7 +337,55 @@
],
"description": "Symfony Yaml Component",
"homepage": "http://symfony.com",
"time": "2013-03-23 01:54:33"
"time": "2013-05-10 00:09:46"
},
{
"name": "twig/twig",
"version": "v1.13.1",
"source": {
"type": "git",
"url": "https://github.com/fabpot/Twig.git",
"reference": "v1.13.1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.13.1",
"reference": "v1.13.1",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"license": [
"BSD-3"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2013-06-06 06:06:01"
}
],
"packages-dev": [
@ -552,16 +593,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "1.2.9",
"version": "1.2.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "1.2.9"
"reference": "1.2.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.9",
"reference": "1.2.9",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.11",
"reference": "1.2.11",
"shasum": ""
},
"require": {
@ -570,6 +611,9 @@
"phpunit/php-text-template": ">=1.1.1@stable",
"phpunit/php-token-stream": ">=1.1.3@stable"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.0.5"
@ -601,7 +645,7 @@
"testing",
"xunit"
],
"time": "2013-02-26 18:55:56"
"time": "2013-05-23 18:23:24"
},
{
"name": "phpunit/php-file-iterator",
@ -783,16 +827,16 @@
},
{
"name": "phpunit/phpunit",
"version": "3.7.19",
"version": "3.7.21",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3.7.19"
"reference": "3.7.21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.19",
"reference": "3.7.19",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.21",
"reference": "3.7.21",
"shasum": ""
},
"require": {
@ -806,7 +850,7 @@
"phpunit/php-text-template": ">=1.1.1",
"phpunit/php-timer": ">=1.0.2,<1.1.0",
"phpunit/phpunit-mock-objects": ">=1.2.0,<1.3.0",
"symfony/yaml": ">=2.0.0,<2.3.0"
"symfony/yaml": ">=2.0,<3.0"
},
"require-dev": {
"pear-pear/pear": "1.9.4"
@ -853,7 +897,7 @@
"testing",
"xunit"
],
"time": "2013-03-25 11:45:06"
"time": "2013-05-23 18:54:29"
},
{
"name": "phpunit/phpunit-mock-objects",
@ -906,17 +950,17 @@
},
{
"name": "symfony/browser-kit",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/BrowserKit",
"source": {
"type": "git",
"url": "https://github.com/symfony/BrowserKit.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/BrowserKit/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/BrowserKit/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -956,17 +1000,17 @@
},
{
"name": "symfony/css-selector",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/CssSelector",
"source": {
"type": "git",
"url": "https://github.com/symfony/CssSelector.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/CssSelector/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/CssSelector/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -994,21 +1038,21 @@
],
"description": "Symfony CssSelector Component",
"homepage": "http://symfony.com",
"time": "2013-01-09 08:51:07"
"time": "2013-05-17 00:31:34"
},
{
"name": "symfony/dom-crawler",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/DomCrawler",
"source": {
"type": "git",
"url": "https://github.com/symfony/DomCrawler.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -1042,21 +1086,21 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "http://symfony.com",
"time": "2013-03-27 17:13:16"
"time": "2013-05-16 00:06:15"
},
{
"name": "symfony/finder",
"version": "v2.1.10",
"version": "v2.1.11",
"target-dir": "Symfony/Component/Finder",
"source": {
"type": "git",
"url": "https://github.com/symfony/Finder.git",
"reference": "v2.1.10"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Finder/zipball/v2.1.10",
"reference": "v2.1.10",
"url": "https://api.github.com/repos/symfony/Finder/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -1084,21 +1128,21 @@
],
"description": "Symfony Finder Component",
"homepage": "http://symfony.com",
"time": "2013-03-06 19:26:55"
"time": "2013-05-25 15:47:15"
},
{
"name": "symfony/process",
"version": "v2.1.9",
"version": "v2.1.11",
"target-dir": "Symfony/Component/Process",
"source": {
"type": "git",
"url": "https://github.com/symfony/Process.git",
"reference": "v2.1.9"
"reference": "v2.1.11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Process/zipball/v2.1.9",
"reference": "v2.1.9",
"url": "https://api.github.com/repos/symfony/Process/zipball/v2.1.11",
"reference": "v2.1.11",
"shasum": ""
},
"require": {
@ -1126,7 +1170,7 @@
],
"description": "Symfony Process Component",
"homepage": "http://symfony.com",
"time": "2013-03-23 07:44:01"
"time": "2013-05-06 10:21:56"
}
],
"aliases": [

View file

@ -92,7 +92,7 @@ services:
arguments:
- @user
- @service_container
- @ext.finder
- @style
cron.task_collection:
class: phpbb_di_service_collection
@ -268,15 +268,15 @@ services:
class: phpbb_style_path_provider
template:
class: phpbb_template
class: phpbb_template_twig
arguments:
- %core.root_path%
- %core.php_ext%
- @config
- @user
- @style.resource_locator
- @template_context
- @ext.manager
- %core.adm_relative_path%
template_context:
class: phpbb_template_context

View file

@ -46,6 +46,7 @@
<ol>
<li><a href="#changelog">Changelog</a>
<ol style="list-style-type: lower-roman;">
<li><a href="#v3011">Changes since 3.0.11</a></li>
<li><a href="#v3010">Changes since 3.0.10</a></li>
<li><a href="#v309">Changes since 3.0.9</a></li>
<li><a href="#v308">Changes since 3.0.8</a></li>
@ -85,7 +86,151 @@
<div class="content">
<a name="v3010"></a><h3>1.i. Changes since 3.0.10</h3>
<a name="v3011"></a><h3>1.i. Changes since 3.0.11</h3>
<h4>Bug</h4>
<ul>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-6723">PHPBB3-6723</a>] - Empty message in deleted messages in PM history</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7262">PHPBB3-7262</a>] - Clarify docs about is_dynamic not being updated by set_config()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8319">PHPBB3-8319</a>] - LOCAL_URL not enforced in bbcodes</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9551">PHPBB3-9551</a>] - Mysql fulltext index creation fails due to partial collation change</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9975">PHPBB3-9975</a>] - Hard coded language in sessions.php</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10184">PHPBB3-10184</a>] - Bots can be sent private messages</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10491">PHPBB3-10491</a>] - Fatal error in functional tests when server returns 404</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10568">PHPBB3-10568</a>] - Modify the trigger language when you edit a PM</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10602">PHPBB3-10602</a>] - A bug in mail queue processing</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10661">PHPBB3-10661</a>] - UCP &gt; PM &gt; Compose &gt; enumerated recipients &gt; BCC group misses a &amp;nbsp; (prosilver)</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10678">PHPBB3-10678</a>] - Provide Firebird, Oracle, and increased MSSQL support in unit tests</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10772">PHPBB3-10772</a>] - trigger_error is using the default style</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10789">PHPBB3-10789</a>] - PM print template (prosilver) with unnecessary variables</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10820">PHPBB3-10820</a>] - Display images directly in IE9 and 10 instead of download</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10828">PHPBB3-10828</a>] - PostgreSQL dbal tests try to connect to the database named as user specified in configuration</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10838">PHPBB3-10838</a>] - Functional tests are not mentioned in RUNNING_TESTS.txt</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10840">PHPBB3-10840</a>] - If you add a member to a group, the form_token can be set to 0 if the creation_time is 0 too. Maybe even if creation_time is unchanged.</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10848">PHPBB3-10848</a>] - Wrong redirect to installer from acp</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10850">PHPBB3-10850</a>] - create_schema_files.php is not creating the oracle or postgres' schema file properly</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10879">PHPBB3-10879</a>] - prosilver: attachment-link will be displayed wrong, when filename is too long </li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10880">PHPBB3-10880</a>] - m_approve should not imply f_noapprove</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10896">PHPBB3-10896</a>] - board_email &amp; board_contact are not validated as email addresses in ACP</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10897">PHPBB3-10897</a>] - Bot Definitions are outdated</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10918">PHPBB3-10918</a>] - docs/INSTALL.html claims there are tar.gz packages</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10943">PHPBB3-10943</a>] - Search Box should display keywords entered by the user</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10967">PHPBB3-10967</a>] - PHPBB_USE_BOARD_URL_PATH not implemented in posting_gen_topic_icons</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10986">PHPBB3-10986</a>] - Invalid email message ids because config variable server_name is used even when force server URL settings is disabled</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10995">PHPBB3-10995</a>] - Return value of $db-&gt;sql_fetchrow() on empty tables is not consistent on mssqlnative</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10996">PHPBB3-10996</a>] - Travis tests fail on Postgres because database does not exist</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11034">PHPBB3-11034</a>] - The functional test case framework does not install a full board each time</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11066">PHPBB3-11066</a>] - MSSQLnative driver contains debug code error_reporting(E_ALL)</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11069">PHPBB3-11069</a>] - missing closing span in subsilver2 simple_footer.html</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11081">PHPBB3-11081</a>] - Duplicated /TD in styles/subsilver2/template/catpcha_qa.html</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11093">PHPBB3-11093</a>] - acp_users_overview.html has a wrongly placed &lt;/dd&gt;</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11094">PHPBB3-11094</a>] - prosilver: searching for users: no textbox for Jabber</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11105">PHPBB3-11105</a>] - Missing mandatory space in meta http-equiv=refresh</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11112">PHPBB3-11112</a>] - phpBB Footer Link should be SSL</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11122">PHPBB3-11122</a>] - Update docs/AUTHORS for 3.0.12-RC1</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11144">PHPBB3-11144</a>] - {FORUM_NAME} is not filled in login mask when logging into a password protected forum</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11145">PHPBB3-11145</a>] - ATTACHED_IMAGE_NOT_IMAGE thrown because of file limit in php.ini</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11158">PHPBB3-11158</a>] - modules table lacks acl_u_sig for signature module</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11159">PHPBB3-11159</a>] - Coding guidelines: static public</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11164">PHPBB3-11164</a>] - Composer not finding symfony/config in PHP 5.3.3</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11178">PHPBB3-11178</a>] - database_update.php should not set error_reporting to E_ALL</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11186">PHPBB3-11186</a>] - Database unit tests fail on windows using sqlite2</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11190">PHPBB3-11190</a>] - Functional tests do not clear the cache between each test</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11196">PHPBB3-11196</a>] - /includes/session.php sends 401 HTTP status with &quot;Not authorized&quot; instead of &quot;Unauthorized&quot;</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11219">PHPBB3-11219</a>] - Database sequences are not updated for tests using fixtures with auto_incremented columns</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11227">PHPBB3-11227</a>] - @return void -&gt; @return null</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11233">PHPBB3-11233</a>] - Anonymous can be selected as a PM recipient</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11248">PHPBB3-11248</a>] - CRLF line endings</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11262">PHPBB3-11262</a>] - .lock files are not in .gitignore</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11265">PHPBB3-11265</a>] - Functional tests do not assert that board installation succeeded</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11269">PHPBB3-11269</a>] - Travis functional test case errors</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11278">PHPBB3-11278</a>] - Firebird tables are not removed correctly on 3.0.9-rc1 update</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11288">PHPBB3-11288</a>] - Search fooled by hyphens</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11291">PHPBB3-11291</a>] - &quot;Could not open input file: ../composer.phar&quot; error during phing's create-package</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11292">PHPBB3-11292</a>] - Newlines removed in display of PM reports, no clickable links in PM reports</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11301">PHPBB3-11301</a>] - &quot;String offset cast occured&quot; error on PHP 5.4</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11304">PHPBB3-11304</a>] - check_form_key breaks in tests when form is submitted in the same second it is retrieved</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11343">PHPBB3-11343</a>] - Loose string comparison during new password activation</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11355">PHPBB3-11355</a>] - Incorrect error message when no user selected for action on group membership management page</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11358">PHPBB3-11358</a>] - Success message even withot selecting a user and performing a group operation</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11361">PHPBB3-11361</a>] - &quot;Array to string conversion&quot; error in $user-&gt;format_date()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11493">PHPBB3-11493</a>] - Functional tests should fail if any debug output is made</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11517">PHPBB3-11517</a>] - Numbering is wrong in coding guidelines</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11536">PHPBB3-11536</a>] - Installer incorrectly removes /install from script_path</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11537">PHPBB3-11537</a>] - UCP group manage page's error box differs heavily from the rest of the UCP</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11538">PHPBB3-11538</a>] - SQL error on UCP groups manage page caused by setting color to 7 characters long string</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11544">PHPBB3-11544</a>] - Add admin_login() to 3.0 functional test case</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11545">PHPBB3-11545</a>] - is_absolute() should not depend on DIRECTORY_SEPARATOR</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11546">PHPBB3-11546</a>] - is_absolute() throws E_NOTICE for empty string</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11547">PHPBB3-11547</a>] - Test fixtures do not support utf8 characters</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11548">PHPBB3-11548</a>] - Untranslated TOO_SHORT in UCP &quot;Manage Groups&quot;</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11566">PHPBB3-11566</a>] - Reporting a post should require a captcha to be solved by guests</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11568">PHPBB3-11568</a>] - Functional tests fail with retrieving install pages using file_get_contents</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11575">PHPBB3-11575</a>] - phpbb_dbal_order_lower_test::test_cross_join should be called test_order_lower</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11578">PHPBB3-11578</a>] - Missing underscore after function prefix in validate_data()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11579">PHPBB3-11579</a>] - Add unit tests for validate_data()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11580">PHPBB3-11580</a>] - Avoid API Limit from composer downloads on github</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11588">PHPBB3-11588</a>] - install/install_update.php should use version.phpbb.com instead of www</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11590">PHPBB3-11590</a>] - Close database connections from tests whenever possible</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11601">PHPBB3-11601</a>] - Allow manual resync of database columns in unit tests not only on fixture load</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11603">PHPBB3-11603</a>] - git-tools use invalid api urls</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11604">PHPBB3-11604</a>] - Functional tests fail when phpBB can not create the config file</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11617">PHPBB3-11617</a>] - Missing U_ACTION in acp_captcha.php</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11618">PHPBB3-11618</a>] - Template tests fail on some systems due to a PHP error in glob()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11619">PHPBB3-11619</a>] - get_remote_file() should use HTTP 1.0</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11630">PHPBB3-11630</a>] - Improvements to the PHP lint pre-commit hook</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11644">PHPBB3-11644</a>] - Skip phpbb_dbal_order_lower_test on MySQL 5.6</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11662">PHPBB3-11662</a>] - &quot;occured&quot; should be &quot;occurred&quot;</li>
</ul>
<h4>Improvement</h4>
<ul>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8743">PHPBB3-8743</a>] - New topic / reply notifications do not contain author's name.</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10050">PHPBB3-10050</a>] - subsilver2: Do not show &quot;Mark topics as read&quot; when there are no topics</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10205">PHPBB3-10205</a>] - More informative reporting of errors when database connection fails (MySQL and others)</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10716">PHPBB3-10716</a>] - PHP-parse all php files as part of the test suite</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10841">PHPBB3-10841</a>] - Disable style and language selectors if there's only one installed.</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10854">PHPBB3-10854</a>] - sql server drop default constraint when dropping column </li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10865">PHPBB3-10865</a>] - Updated and Added to docs/INSTALL.html</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10873">PHPBB3-10873</a>] - Change language entry for deleted PMs</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10981">PHPBB3-10981</a>] - Upgrade Goutte and use Composer for Installation</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11131">PHPBB3-11131</a>] - Phrasing &amp; semantics of Board settings</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11162">PHPBB3-11162</a>] - Get rid of $db-&gt;sql_return_on_error(true) trickery when splitting/merging topics</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11192">PHPBB3-11192</a>] - Add Tebibyte to get_formatted_filesize()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11202">PHPBB3-11202</a>] - Add response status checks to functional tests</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11220">PHPBB3-11220</a>] - Improve tooltip explaining the [list=] - BBcode</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11238">PHPBB3-11238</a>] - Specify goutte version</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11285">PHPBB3-11285</a>] - Use more granularity in dependency checks in compress test</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11293">PHPBB3-11293</a>] - Prefer mysqli over mysql due to php 5.5 alpha 2 deprecating mysql</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11294">PHPBB3-11294</a>] - Update extension list in running tests doc</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11368">PHPBB3-11368</a>] - Latest pm reports row count</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11583">PHPBB3-11583</a>] - InnoDB supports FULLTEXT index since MySQL 5.6.4.</li>
</ul>
<h4>Sub-task</h4>
<ul>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10974">PHPBB3-10974</a>] - Move tests/mock_user.php to tests/mock/user.php</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11009">PHPBB3-11009</a>] - Backport phing build.xml from develop to develop-olympus so it uses composer.</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11540">PHPBB3-11540</a>] - Add unit tests for (phpbb_)is_absolute()</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11541">PHPBB3-11541</a>] - Add unit tests for style_select() in functions.php</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11542">PHPBB3-11542</a>] - Add unit tests for language_select() in functions.php</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11543">PHPBB3-11543</a>] - Add unit tests for obtain online functions in functions.php</li>
</ul>
<h4>Task</h4>
<ul>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10877">PHPBB3-10877</a>] - Have bamboo generate and publish a phpBB package for every build.</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11045">PHPBB3-11045</a>] - Add unit tests for the compress class</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11059">PHPBB3-11059</a>] - Fix README logo</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11060">PHPBB3-11060</a>] - Fix travis.yml pyrus config</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11240">PHPBB3-11240</a>] - Turn on PHPUnit's verbose mode on Travis</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11324">PHPBB3-11324</a>] - Add PHP 5.5 environment on Travis-CI</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11337">PHPBB3-11337</a>] - Run functional tests on Travis CI</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11513">PHPBB3-11513</a>] - Install PHPUnit via Composer's require-dev to simplify test running (no need for pear)</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11526">PHPBB3-11526</a>] - Increase composer minimum-stability from beta to stable</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11527">PHPBB3-11527</a>] - Upgrade composer.phar to 1.0.0-alpha7</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11529">PHPBB3-11529</a>] - Rename RUNNING_TESTS file to .md file to render it on GitHub</li>
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11576">PHPBB3-11576</a>] - Make phpBB Test Suite MySQL behave at least as strict as phpBB MySQL driver</li>
</ul>
<a name="v3010"></a><h3>1.ii. Changes since 3.0.10</h3>
<h4>Bug</h4>
<ul>
@ -210,7 +355,7 @@
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10909">PHPBB3-10909</a>] - Update Travis Test Configuration: Travis no longer supports PHP 5.3.2</li>
</ul>
<a name="v309"></a><h3>1.ii. Changes since 3.0.9</h3>
<a name="v309"></a><h3>1.iii. Changes since 3.0.9</h3>
<h4>Bug</h4>
<ul>
@ -346,7 +491,7 @@
<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10480">PHPBB3-10480</a>] - Automate changelog building</li>
</ul>
<a name="v308"></a><h3>1.iii. Changes since 3.0.8</h3>
<a name="v308"></a><h3>1.iv. Changes since 3.0.8</h3>
<h4> Bug
</h4>
@ -714,7 +859,7 @@
</ul>
<a name="v307-PL1"></a><h3>1.iv. Changes since 3.0.7-PL1</h3>
<a name="v307-PL1"></a><h3>1.v. Changes since 3.0.7-PL1</h3>
<h4> Security
</h4>
<ul>
@ -1172,13 +1317,13 @@
</ul>
<a name="v307"></a><h3>1.iv. Changes since 3.0.7</h3>
<a name="v307"></a><h3>1.vi. Changes since 3.0.7</h3>
<ul>
<li>[Sec] Do not expose forum content of forums with ACL entries but no actual permission in ATOM Feeds. (Bug #58595)</li>
</ul>
<a name="v306"></a><h3>1.vi. Changes since 3.0.6</h3>
<a name="v306"></a><h3>1.vii. Changes since 3.0.6</h3>
<ul>
<li>[Fix] Allow ban reason and length to be selected and copied in ACP and subsilver2 MCP. (Bug #51095)</li>
@ -1282,7 +1427,7 @@
</ul>
<a name="v305"></a><h3>1.vii. Changes since 3.0.5</h3>
<a name="v305"></a><h3>1.viii. Changes since 3.0.5</h3>
<ul>
<li>[Fix] Allow whitespaces in avatar gallery names. (Bug #44955)</li>
@ -1504,7 +1649,7 @@
<li>[Feature] Send anonymous statistical information to phpBB on installation and update (optional).</li>
</ul>
<a name="v304"></a><h3>1.viii. Changes since 3.0.4</h3>
<a name="v304"></a><h3>1.ix. Changes since 3.0.4</h3>
<ul>
<li>[Fix] Delete user entry from ban list table upon user deletion (Bug #40015 - Patch by TerraFrost)</li>
@ -1593,7 +1738,7 @@
<li>[Sec] Only use forum id supplied for posting if global announcement detected. (Reported by nickvergessen)</li>
</ul>
<a name="v303"></a><h3>1.ix. Changes since 3.0.3</h3>
<a name="v303"></a><h3>1.x. Changes since 3.0.3</h3>
<ul>
<li>[Fix] Allow mixed-case template directories to be inherited (Bug #36725)</li>
@ -1625,7 +1770,7 @@
<li>[Sec] Ask for forum password if post within passworded forum quoted in private message. (Reported by nickvergessen)</li>
</ul>
<a name="v302"></a><h3>1.x. Changes since 3.0.2</h3>
<a name="v302"></a><h3>1.xi. Changes since 3.0.2</h3>
<ul>
<li>[Fix] Correctly set topic starter if first post in topic removed (Bug #30575 - Patch by blueray2048)</li>
@ -1724,7 +1869,7 @@
<li>[Sec Precaution] Stricter validation of the HTTP_HOST header (Thanks to Techie-Micheal et al for pointing out possible issues in derived code)</li>
</ul>
<a name="v301"></a><h3>1.xi. Changes since 3.0.1</h3>
<a name="v301"></a><h3>1.xii. Changes since 3.0.1</h3>
<ul>
<li>[Fix] Ability to set permissions on non-mysql dbms (Bug #24955)</li>
@ -1772,7 +1917,7 @@
<li>[Sec] Only allow urls gone through redirect() being used within login_box(). (thanks nookieman)</li>
</ul>
<a name="v300"></a><h3>1.xii Changes since 3.0.0</h3>
<a name="v300"></a><h3>1.xiii Changes since 3.0.0</h3>
<ul>
<li>[Change] Validate birthdays (Bug #15004)</li>
@ -1843,7 +1988,7 @@
<li>[Fix] Find and display colliding usernames correctly when converting from one database to another (Bug #23925)</li>
</ul>
<a name="v30rc8"></a><h3>1.xiii. Changes since 3.0.RC8</h3>
<a name="v30rc8"></a><h3>1.xiv. Changes since 3.0.RC8</h3>
<ul>
<li>[Fix] Cleaned usernames contain only single spaces, so &quot;a_name&quot; and &quot;a__name&quot; are treated as the same name (Bug #15634)</li>
@ -1852,7 +1997,7 @@
<li>[Fix] Call garbage_collection() within database updater to correctly close connections (affects Oracle for example)</li>
</ul>
<a name="v30rc7"></a><h3>1.xiv. Changes since 3.0.RC7</h3>
<a name="v30rc7"></a><h3>1.xv. Changes since 3.0.RC7</h3>
<ul>
<li>[Fix] Fixed MSSQL related bug in the update system</li>
@ -1887,7 +2032,7 @@
<li>[Fix] No duplication of active topics (Bug #15474)</li>
</ul>
<a name="v30rc6"></a><h3>1.xv. Changes since 3.0.RC6</h3>
<a name="v30rc6"></a><h3>1.xvi. Changes since 3.0.RC6</h3>
<ul>
<li>[Fix] Submitting language changes using acp_language (Bug #14736)</li>
@ -1897,7 +2042,7 @@
<li>[Fix] Able to request new password (Bug #14743)</li>
</ul>
<a name="v30rc5"></a><h3>1.xvi. Changes since 3.0.RC5</h3>
<a name="v30rc5"></a><h3>1.xvii. Changes since 3.0.RC5</h3>
<ul>
<li>[Feature] Removing constant PHPBB_EMBEDDED in favor of using an exit_handler(); the constant was meant to achive this more or less.</li>
@ -1960,7 +2105,7 @@
<li>[Sec] New password hashing mechanism for storing passwords (#i42)</li>
</ul>
<a name="v30rc4"></a><h3>1.xvii. Changes since 3.0.RC4</h3>
<a name="v30rc4"></a><h3>1.xviii. Changes since 3.0.RC4</h3>
<ul>
<li>[Fix] MySQL, PostgreSQL and SQLite related database fixes (Bug #13862)</li>
@ -2011,7 +2156,7 @@
<li>[Fix] odbc_autocommit causing existing result sets to be dropped (Bug #14182)</li>
</ul>
<a name="v30rc3"></a><h3>1.xviii. Changes since 3.0.RC3</h3>
<a name="v30rc3"></a><h3>1.xix. Changes since 3.0.RC3</h3>
<ul>
<li>[Fix] Fixing some subsilver2 and prosilver style issues</li>
@ -2120,7 +2265,7 @@
</ul>
<a name="v30rc2"></a><h3>1.xviv. Changes since 3.0.RC2</h3>
<a name="v30rc2"></a><h3>1.xx. Changes since 3.0.RC2</h3>
<ul>
<li>[Fix] Re-allow searching within the memberlist</li>
@ -2166,7 +2311,7 @@
</ul>
<a name="v30rc1"></a><h3>1.xx. Changes since 3.0.RC1</h3>
<a name="v30rc1"></a><h3>1.xxi. Changes since 3.0.RC1</h3>
<ul>
<li>[Fix] (X)HTML issues within the templates (Bug #11255, #11255)</li>

View file

@ -112,8 +112,8 @@ class acp_bbcodes
{
$template->assign_block_vars('token', array(
'TOKEN' => '{' . $token . '}',
'EXPLAIN' => $token_explain)
);
'EXPLAIN' => ($token === 'LOCAL_URL') ? sprintf($token_explain, generate_board_url() . '/') : $token_explain,
));
}
return;
@ -347,6 +347,9 @@ class acp_bbcodes
'LOCAL_URL' => array(
'!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')"
),
'RELATIVE_URL' => array(
'!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')"
),
'EMAIL' => array(
'!(' . get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')"
),
@ -373,6 +376,7 @@ class acp_bbcodes
$sp_tokens = array(
'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))(?-i)',
'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)',
'RELATIVE_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)',
'EMAIL' => '(' . get_preg_expression('email') . ')',
'TEXT' => '(.*?)',
'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)',
@ -429,7 +433,11 @@ class acp_bbcodes
$fp_replace = str_replace($token, $replace, $fp_replace);
$sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match);
$sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace);
// Prepend the board url to local relative links
$replace_prepend = ($token_type === 'LOCAL_URL') ? generate_board_url() . '/' : '';
$sp_replace = str_replace($token, $replace_prepend . '${' . ($n + 1) . '}', $sp_replace);
}
$fp_match = '!' . $fp_match . '!' . $modifiers;

View file

@ -528,10 +528,10 @@ class acp_board
$old_auth_config = array();
foreach ($auth_providers as $provider)
{
if ($fields = $provider->acp($this->new_config))
if ($fields = $provider->acp())
{
// Check if we need to create config fields for this plugin and save config when submit was pressed
foreach ($fields['config'] as $field)
foreach ($fields as $field)
{
if (!isset($config[$field]))
{
@ -655,15 +655,14 @@ class acp_board
foreach ($auth_providers as $provider)
{
$fields = $provider->acp($this->new_config);
if ($fields['tpl'])
$auth_tpl = $provider->get_acp_template($this->new_config);
if ($auth_tpl)
{
$template->assign_vars($auth_tpl['TEMPLATE_VARS']);
$template->assign_block_vars('auth_tpl', array(
'TPL' => $fields['tpl'],
'TEMPLATE_FILE' => $auth_tpl['TEMPLATE_FILE'],
));
}
unset($fields);
}
}
}
@ -678,8 +677,12 @@ class acp_board
$auth_plugins = array();
$auth_providers = $phpbb_container->get('auth.provider_collection');
foreach($auth_providers as $key => $value)
foreach ($auth_providers as $key => $value)
{
if (!($value instanceof phpbb_auth_provider_interface))
{
continue;
}
$auth_plugins[] = str_replace('auth.provider.', '', $key);
}

View file

@ -410,7 +410,7 @@ class acp_groups
if ($validation_error = validate_data($submit_ary, $validation_checks))
{
// Replace "error" string with its real, localised form
$error = array_merge($error, array_map(array(&$user, 'lang'), $validation_error));
$error = array_merge($error, $validation_error);
}
if (!sizeof($error))
@ -507,6 +507,7 @@ class acp_groups
if (sizeof($error))
{
$error = array_map(array(&$user, 'lang'), $error);
$group_rank = $submit_ary['rank'];
$group_desc_data = array(

View file

@ -20,7 +20,7 @@ if (!defined('IN_PHPBB'))
*
* @package auth
*/
class phpbb_auth_provider_apache implements phpbb_auth_provider_interface
class phpbb_auth_provider_apache extends phpbb_auth_provider_base
{
/**
* Apache Authentication Constructor
@ -256,20 +256,4 @@ class phpbb_auth_provider_apache implements phpbb_auth_provider_interface
return false;
}
/**
* {@inheritdoc}
*/
public function acp($new)
{
return;
}
/**
* {@inheritdoc}
*/
public function logout($data, $new_session)
{
return;
}
}

View file

@ -0,0 +1,72 @@
<?php
/**
*
* @package auth
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Base authentication provider class that all other providers should implement
*
* @package auth
*/
abstract class phpbb_auth_provider_base implements phpbb_auth_provider_interface
{
/**
* {@inheritdoc}
*/
public function init()
{
return;
}
/**
* {@inheritdoc}
*/
public function autologin()
{
return;
}
/**
* {@inheritdoc}
*/
public function acp()
{
return;
}
/**
* {@inheritdoc}
*/
public function get_acp_template($new_config)
{
return;
}
/**
* {@inheritdoc}
*/
public function logout($data, $new_session)
{
return;
}
/**
* {@inheritdoc}
*/
public function validate_session($user)
{
return;
}
}

View file

@ -22,7 +22,7 @@ if (!defined('IN_PHPBB'))
*
* @package auth
*/
class phpbb_auth_provider_db implements phpbb_auth_provider_interface
class phpbb_auth_provider_db extends phpbb_auth_provider_base
{
/**
@ -45,14 +45,6 @@ class phpbb_auth_provider_db implements phpbb_auth_provider_interface
$this->php_ext = $php_ext;
}
/**
* {@inheritdoc}
*/
public function init()
{
return;
}
/**
* {@inheritdoc}
*/
@ -302,36 +294,4 @@ class phpbb_auth_provider_db implements phpbb_auth_provider_interface
'user_row' => $row,
);
}
/**
* {@inheritdoc}
*/
public function autologin()
{
return;
}
/**
* {@inheritdoc}
*/
public function acp($new)
{
return;
}
/**
* {@inheritdoc}
*/
public function logout($data, $new_session)
{
return;
}
/**
* {@inheritdoc}
*/
public function validate_session($user)
{
return;
}
}

View file

@ -60,16 +60,28 @@ interface phpbb_auth_provider_interface
* This function is used to output any required fields in the authentication
* admin panel. It also defines any required configuration table fields.
*
* @param array $new Contains the new configuration values that have
* been set in acp_board.
* @return array|null Returns null if not implemented or an array of the
* form:
* configuration fields of the provider.
*/
public function acp();
/**
* This function updates the template with variables related to the acp
* options with whatever configuraton values are passed to it as an array.
* It then returns the name of the acp file related to this authentication
* provider.
* @param array $new_config Contains the new configuration values that
* have been set in acp_board.
* @return array|null Returns null if not implemented or an array with
* the template file name and an array of the vars
* that the template needs that must conform to the
* following example:
* array(
* 'tpl' => string
* 'config' => array
* 'TEMPLATE_FILE' => string,
* 'TEMPLATE_VARS' => array(...),
* )
*/
public function acp($new);
public function get_acp_template($new_config);
/**
* Performs additional actions during logout.

View file

@ -22,7 +22,7 @@ if (!defined('IN_PHPBB'))
*
* @package auth
*/
class phpbb_auth_provider_ldap implements phpbb_auth_provider_interface
class phpbb_auth_provider_ldap extends phpbb_auth_provider_base
{
/**
* LDAP Authentication Constructor
@ -286,56 +286,32 @@ class phpbb_auth_provider_ldap implements phpbb_auth_provider_interface
/**
* {@inheritdoc}
*/
public function autologin()
public function acp()
{
return;
// These are fields required in the config table
return array(
'ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password',
);
}
/**
* {@inheritdoc}
*/
public function acp($new)
public function get_acp_template($new_config)
{
$tpl = '
<dl>
<dt><label for="ldap_server">' . $this->user->lang['LDAP_SERVER'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_SERVER_EXPLAIN'] . '</span></dt>
<dd><input type="text" id="ldap_server" size="40" name="config[ldap_server]" value="' . $new['ldap_server'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_port">' . $this->user->lang['LDAP_PORT'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_PORT_EXPLAIN'] . '</span></dt>
<dd><input type="text" id="ldap_port" size="40" name="config[ldap_port]" value="' . $new['ldap_port'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_dn">' . $this->user->lang['LDAP_DN'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_DN_EXPLAIN'] . '</span></dt>
<dd><input type="text" id="ldap_dn" size="40" name="config[ldap_base_dn]" value="' . $new['ldap_base_dn'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_uid">' . $this->user->lang['LDAP_UID'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_UID_EXPLAIN'] . '</span></dt>
<dd><input type="text" id="ldap_uid" size="40" name="config[ldap_uid]" value="' . $new['ldap_uid'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_user_filter">' . $this->user->lang['LDAP_USER_FILTER'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_USER_FILTER_EXPLAIN'] . '</span></dt>
<dd><input type="text" id="ldap_user_filter" size="40" name="config[ldap_user_filter]" value="' . $new['ldap_user_filter'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_email">' . $this->user->lang['LDAP_EMAIL'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_EMAIL_EXPLAIN'] . '</span></dt>
<dd><input type="email" id="ldap_email" size="40" name="config[ldap_email]" value="' . $new['ldap_email'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_user">' . $this->user->lang['LDAP_USER'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_USER_EXPLAIN'] . '</span></dt>
<dd><input type="text" id="ldap_user" size="40" name="config[ldap_user]" value="' . $new['ldap_user'] . '" /></dd>
</dl>
<dl>
<dt><label for="ldap_password">' . $this->user->lang['LDAP_PASSWORD'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_PASSWORD_EXPLAIN'] . '</span></dt>
<dd><input type="password" id="ldap_password" size="40" name="config[ldap_password]" value="' . $new['ldap_password'] . '" autocomplete="off" /></dd>
</dl>
';
// These are fields required in the config table
return array(
'tpl' => $tpl,
'config' => array('ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password')
'TEMPLATE_FILE' => 'auth_provider_ldap.html',
'TEMPLATE_VARS' => array(
'AUTH_LDAP_DN' => $new_config['ldap_base_dn'],
'AUTH_LDAP_EMAIL' => $new_config['ldap_email'],
'AUTH_LDAP_PASSORD' => $new_config['ldap_password'],
'AUTH_LDAP_PORT' => $new_config['ldap_port'],
'AUTH_LDAP_SERVER' => $new_config['ldap_server'],
'AUTH_LDAP_UID' => $new_config['ldap_uid'],
'AUTH_LDAP_USER' => $new_config['ldap_user'],
'AUTH_LDAP_USER_FILTER' => $new_config['ldap_user_filter'],
),
);
}
@ -367,20 +343,4 @@ class phpbb_auth_provider_ldap implements phpbb_auth_provider_interface
{
return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string);
}
/**
* {@inheritdoc}
*/
public function logout($data, $new_session)
{
return;
}
/**
* {@inheritdoc}
*/
public function validate_session($user)
{
return;
}
}

View file

@ -77,6 +77,32 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver
}
elseif (!empty($this->config['allow_avatar_remote_upload']) && !empty($url))
{
if (!preg_match('#^(http|https|ftp)://#i', $url))
{
$url = 'http://' . $url;
}
if (!function_exists('validate_data'))
{
require($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$validate_array = validate_data(
array(
'url' => $url,
),
array(
'url' => array('string', true, 5, 255),
)
);
$error = array_merge($error, $validate_array);
if (!empty($error))
{
return false;
}
$file = $upload->remote_upload($url);
}
else

View file

@ -134,11 +134,11 @@ class bbcode
$style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider(), $phpbb_root_path);
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $user, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template);
$style->set_style();
$template->set_filenames(array('bbcode.html' => 'bbcode.html'));
$this->template_filename = $style_resource_locator->get_source_file_for_handle('bbcode.html');
$this->template_filename = $template->get_source_file_for_handle('bbcode.html');
}
$bbcode_ids = $rowset = $sql = array();

View file

@ -37,16 +37,24 @@ class phpbb_controller_resolver implements ControllerResolverInterface
*/
protected $container;
/**
* phpbb_style object
* @var phpbb_style
*/
protected $style;
/**
* Construct method
*
* @param phpbb_user $user User Object
* @param ContainerInterface $container ContainerInterface object
* @param phpbb_style $style
*/
public function __construct(phpbb_user $user, ContainerInterface $container)
public function __construct(phpbb_user $user, ContainerInterface $container, phpbb_style $style = null)
{
$this->user = $user;
$this->container = $container;
$this->style = $style;
}
/**
@ -80,6 +88,24 @@ class phpbb_controller_resolver implements ControllerResolverInterface
$controller_object = $this->container->get($service);
/*
* If this is an extension controller, we'll try to automatically set
* the style paths for the extension (the ext author can change them
* if necessary).
*/
$controller_dir = explode('_', get_class($controller_object));
// 0 phpbb, 1 ext, 2 vendor, 3 extension name, ...
if (!is_null($this->style) && isset($controller_dir[3]) && $controller_dir[1] === 'ext')
{
$controller_style_dir = 'ext/' . $controller_dir[2] . '/' . $controller_dir[3] . '/styles';
if (is_dir($controller_style_dir))
{
$this->style->set_style(array($controller_style_dir, 'styles'));
}
}
return array($controller_object, $method);
}

View file

@ -27,8 +27,8 @@ class phpbb_db_migration_data_30x_3_0_9_rc1 extends phpbb_db_migration
'COLUMNS' => array(
// this column was removed from the database updater
// after 3.0.9-RC3 was released. It might still exist
// in 3.0.9-RCX installations and has to be dropped in
// 3.0.12 after the db_tools class is capable of properly
// in 3.0.9-RCX installations and has to be dropped as
// soon as the db_tools class is capable of properly
// removing a primary key.
// 'attempt_id' => array('UINT', NULL, 'auto_increment'),
'attempt_ip' => array('VCHAR:40', ''),

View file

@ -0,0 +1,57 @@
<?php
/**
*
* @package migration
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_db_migration_data_30x_local_url_bbcode extends phpbb_db_migration
{
static public function depends_on()
{
return array('phpbb_db_migration_data_30x_3_0_12_rc1');
}
public function update_data()
{
return array(
array('custom', array(array($this, 'update_local_url_bbcode'))),
);
}
/**
* Update BBCodes that currently use the LOCAL_URL tag
*
* To fix http://tracker.phpbb.com/browse/PHPBB3-8319 we changed
* the second_pass_replace value, so that needs updating for existing ones
*/
public function update_local_url_bbcode()
{
$sql = 'SELECT *
FROM ' . BBCODES_TABLE . '
WHERE bbcode_match ' . $this->db->sql_like_expression($this->db->any_char . 'LOCAL_URL' . $this->db->any_char);
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if (!class_exists('acp_bbcodes'))
{
global $phpEx;
phpbb_require_updated('includes/acp/acp_bbcodes.' . $phpEx);
}
$bbcode_match = $row['bbcode_match'];
$bbcode_tpl = $row['bbcode_tpl'];
$acp_bbcodes = new acp_bbcodes();
$sql_ary = $acp_bbcodes->build_regexp($bbcode_match, $bbcode_tpl);
$sql = 'UPDATE ' . BBCODES_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE bbcode_id = ' . (int) $row['bbcode_id'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
}
}

View file

@ -44,7 +44,7 @@ abstract class phpbb_db_migration
/** @var string */
protected $php_ext;
/** @var array Errors, if any occured */
/** @var array Errors, if any occurred */
protected $errors;
/** @var array List of queries executed through $this->sql_query() */

View file

@ -20,6 +20,71 @@ if (!defined('IN_PHPBB'))
exit;
}
/**
* Get DB connection from config.php.
*
* Used to bootstrap the container.
*
* @param string $config_file
* @return phpbb_db_driver
*/
function phpbb_bootstrap_db_connection($config_file)
{
require($config_file);
$dbal_driver_class = phpbb_convert_30_dbms_to_31($dbms);
$db = new $dbal_driver_class();
$db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, defined('PHPBB_DB_NEW_LINK'));
return $db;
}
/**
* Get table prefix from config.php.
*
* Used to bootstrap the container.
*
* @param string $config_file
* @return string table prefix
*/
function phpbb_bootstrap_table_prefix($config_file)
{
require($config_file);
return $table_prefix;
}
/**
* Get enabled extensions.
*
* Used to bootstrap the container.
*
* @param string $config_file
* @param string $phpbb_root_path
* @return array enabled extensions
*/
function phpbb_bootstrap_enabled_exts($config_file, $phpbb_root_path)
{
$db = phpbb_bootstrap_db_connection($config_file);
$table_prefix = phpbb_bootstrap_table_prefix($config_file);
$extension_table = $table_prefix.'ext';
$sql = 'SELECT *
FROM ' . $extension_table . '
WHERE ext_active = 1';
$result = $db->sql_query($sql);
$rows = $db->sql_fetchrowset($result);
$db->sql_freeresult($result);
$exts = array();
foreach ($rows as $row)
{
$exts[$row['ext_name']] = $phpbb_root_path . 'ext/' . $row['ext_name'] . '/';
}
return $exts;
}
/**
* Create the ContainerBuilder object
*
@ -79,16 +144,9 @@ function phpbb_create_install_container($phpbb_root_path, $php_ext)
* @param string $php_ext PHP Extension
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_compiled_container(array $extensions, array $passes, $phpbb_root_path, $php_ext)
function phpbb_create_compiled_container($config_file, array $extensions, array $passes, $phpbb_root_path, $php_ext)
{
// Create a temporary container for access to the ext.manager service
$tmp_container = phpbb_create_container($extensions, $phpbb_root_path, $php_ext);
$tmp_container->compile();
// XXX stop writing to global $cache when
// http://tracker.phpbb.com/browse/PHPBB3-11203 is fixed
$GLOBALS['cache'] = $tmp_container->get('cache');
$installed_exts = $tmp_container->get('ext.manager')->all_enabled();
$installed_exts = phpbb_bootstrap_enabled_exts($config_file, $phpbb_root_path);
// Now pass the enabled extension paths into the ext compiler extension
$extensions[] = new phpbb_di_extension_ext($installed_exts);
@ -115,7 +173,7 @@ function phpbb_create_compiled_container(array $extensions, array $passes, $phpb
* @param string $php_ext PHP Extension
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_root_path, $php_ext)
function phpbb_create_dumped_container($config_file, array $extensions, array $passes, $phpbb_root_path, $php_ext)
{
// Check for our cached container; if it exists, use it
$container_filename = phpbb_container_filename($phpbb_root_path, $php_ext);
@ -125,7 +183,7 @@ function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_
return new phpbb_cache_container();
}
$container = phpbb_create_compiled_container($extensions, $passes, $phpbb_root_path, $php_ext);
$container = phpbb_create_compiled_container($config_file, $extensions, $passes, $phpbb_root_path, $php_ext);
// Lastly, we create our cached container class
$dumper = new PhpDumper($container);
@ -155,10 +213,10 @@ function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_
* @param string $php_ext PHP Extension
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_dumped_container_unless_debug(array $extensions, array $passes, $phpbb_root_path, $php_ext)
function phpbb_create_dumped_container_unless_debug($config_file, array $extensions, array $passes, $phpbb_root_path, $php_ext)
{
$container_factory = defined('DEBUG') ? 'phpbb_create_compiled_container' : 'phpbb_create_dumped_container';
return $container_factory($extensions, $passes, $phpbb_root_path, $php_ext);
return $container_factory($config_file, $extensions, $passes, $phpbb_root_path, $php_ext);
}
/**
@ -172,9 +230,11 @@ function phpbb_create_dumped_container_unless_debug(array $extensions, array $pa
*/
function phpbb_create_default_container($phpbb_root_path, $php_ext)
{
$config_file = $phpbb_root_path . 'config.' . $php_ext;
return phpbb_create_dumped_container_unless_debug(
$config_file,
array(
new phpbb_di_extension_config($phpbb_root_path . 'config.' . $php_ext),
new phpbb_di_extension_config($config_file),
new phpbb_di_extension_core($phpbb_root_path),
),
array(

View file

@ -249,7 +249,7 @@ class jabber
return true;
}
// Apparently an error occured...
// Apparently an error occurred...
$this->add_to_log('Error: open_socket() - ' . $errorstr);
return false;
}

View file

@ -27,8 +27,9 @@ class messenger
var $mail_priority = MAIL_NORMAL_PRIORITY;
var $use_queue = true;
var $tpl_obj = NULL;
var $tpl_msg = array();
/** @var phpbb_template */
protected $template;
var $eol = "\n";
/**
@ -210,6 +211,8 @@ class messenger
{
global $config, $phpbb_root_path, $phpEx, $user, $phpbb_extension_manager;
$this->setup_template();
if (!trim($template_file))
{
trigger_error('No template file for emailing set.', E_USER_ERROR);
@ -219,46 +222,43 @@ class messenger
{
// fall back to board default language if the user's language is
// missing $template_file. If this does not exist either,
// $tpl->set_filenames will do a trigger_error
// $this->template->set_filenames will do a trigger_error
$template_lang = basename($config['default_lang']);
}
// tpl_msg now holds a template object we can use to parse the template file
if (!isset($this->tpl_msg[$template_lang . $template_file]))
if ($template_path)
{
$style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider(), $phpbb_root_path);
$tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl);
$this->tpl_msg[$template_lang . $template_file] = $tpl;
$fallback_template_path = false;
if (!$template_path)
$template_paths = array(
$template_path,
);
}
else
{
$template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/';
$template_path .= $template_lang . '/email';
$template_paths = array(
$template_path,
);
// we can only specify default language fallback when the path is not a custom one for which we
// do not know the default language alternative
if ($template_lang !== basename($config['default_lang']))
{
$fallback_template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/';
$fallback_template_path .= basename($config['default_lang']) . '/email';
$template_paths[] = $fallback_template_path;
}
}
$style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), array(), '');
$this->set_template_paths($template_lang . '_email', $template_paths);
$tpl->set_filenames(array(
$this->template->set_filenames(array(
'body' => $template_file . '.txt',
));
}
$this->tpl_obj = &$this->tpl_msg[$template_lang . $template_file];
$this->vars = &$this->tpl_obj->_rootref;
$this->tpl_msg = '';
$this->vars = $this->template->get_template_vars();
return true;
}
@ -268,22 +268,16 @@ class messenger
*/
function assign_vars($vars)
{
if (!is_object($this->tpl_obj))
{
return;
}
$this->setup_template();
$this->tpl_obj->assign_vars($vars);
$this->template->assign_vars($vars);
}
function assign_block_vars($blockname, $vars)
{
if (!is_object($this->tpl_obj))
{
return;
}
$this->setup_template();
$this->tpl_obj->assign_block_vars($blockname, $vars);
$this->template->assign_block_vars($blockname, $vars);
}
/**
@ -316,7 +310,7 @@ class messenger
}
// Parse message through template
$this->msg = trim($this->tpl_obj->assign_display('body'));
$this->msg = trim($this->template->assign_display('body'));
// Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding
$this->msg = str_replace("\r\n", "\n", $this->msg);
@ -643,6 +637,31 @@ class messenger
unset($addresses);
return true;
}
/**
* Setup template engine
*/
protected function setup_template()
{
global $config, $phpbb_root_path, $phpEx, $user, $phpbb_extension_manager;
if ($this->template instanceof phpbb_template)
{
return;
}
$this->template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $user, new phpbb_template_context(), $phpbb_extension_manager);
}
/**
* Set template paths to load
*/
protected function set_template_paths($path_name, $paths)
{
$this->setup_template();
$this->template->set_style_names(array($path_name), $paths);
}
}
/**

View file

@ -455,7 +455,7 @@ class p_master
*/
function load_active($mode = false, $module_url = false, $execute_module = true)
{
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user, $phpbb_style;
$module_path = $this->include_path . $this->p_class;
$icat = request_var('icat', '');
@ -494,6 +494,24 @@ class p_master
// We pre-define the action parameter we are using all over the place
if (defined('IN_ADMIN'))
{
/*
* If this is an extension module, we'll try to automatically set
* the style paths for the extension (the ext author can change them
* if necessary).
*/
$module_dir = explode('_', get_class($this->module));
// 0 phpbb, 1 ext, 2 vendor, 3 extension name, ...
if (isset($module_dir[3]) && $module_dir[1] === 'ext')
{
$module_style_dir = $phpbb_root_path . 'ext/' . $module_dir[2] . '/' . $module_dir[3] . '/adm/style';
if (is_dir($module_style_dir))
{
$phpbb_style->set_custom_style('admin', array($module_style_dir, $phpbb_admin_path . 'style'), array(), '');
}
}
// Is first module automatically enabled a duplicate and the category not passed yet?
if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate'])
{
@ -505,6 +523,24 @@ class p_master
}
else
{
/*
* If this is an extension module, we'll try to automatically set
* the style paths for the extension (the ext author can change them
* if necessary).
*/
$module_dir = explode('_', get_class($this->module));
// 0 phpbb, 1 ext, 2 vendor, 3 extension name, ...
if (isset($module_dir[3]) && $module_dir[1] === 'ext')
{
$module_style_dir = 'ext/' . $module_dir[2] . '/' . $module_dir[3] . '/styles';
if (is_dir($phpbb_root_path . $module_style_dir))
{
$phpbb_style->set_style(array($module_style_dir, 'styles'));
}
}
// If user specified the module url we will use it...
if ($module_url !== false)
{

View file

@ -140,7 +140,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
/**
* Checks for correct MySQL version and stores min/max word length in the config
*
* @return string|bool Language key of the error/incompatiblity occured
* @return string|bool Language key of the error/incompatiblity occurred
*/
public function init()
{

View file

@ -185,7 +185,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
/**
* Checks for correct PostgreSQL version and stores min/max word length in the config
*
* @return string|bool Language key of the error/incompatiblity occured
* @return string|bool Language key of the error/incompatiblity occurred
*/
public function init()
{

View file

@ -404,6 +404,12 @@ class phpbb_session
$method = basename(trim($config['auth_method']));
$provider = $phpbb_container->get('auth.provider.' . $method);
if (!($provider instanceof phpbb_auth_provider_interface))
{
throw new \RuntimeException($provider . ' must implement phpbb_auth_provider_interface');
}
$ret = $provider->validate_session($this->data);
if ($ret !== null && !$ret)
{

View file

@ -85,28 +85,62 @@ class phpbb_style
}
/**
* Set style location based on (current) user's chosen style.
* Get the style tree of the style preferred by the current user
*
* @return array Style tree, most specific first
*/
public function set_style()
public function get_user_style()
{
$style_path = $this->user->style['style_path'];
$style_dirs = ($this->user->style['style_parent_id']) ? array_reverse(explode('/', $this->user->style['style_parent_tree'])) : array();
$style_list = array(
$this->user->style['style_path'],
);
$names = array($style_path);
foreach ($style_dirs as $dir)
if ($this->user->style['style_parent_id'])
{
$names[] = $dir;
$style_list = array_merge($style_list, array_reverse(explode('/', $this->user->style['style_parent_tree'])));
}
// Add 'all' path, used as last fallback path by events and extensions
//$names[] = 'all';
return $style_list;
}
/**
* Set style location based on (current) user's chosen style.
*
* @param array $style_directories The directories to add style paths for
* E.g. array('ext/foo/bar/styles', 'styles')
* Default: array('styles') (phpBB's style directory)
* @return bool true
*/
public function set_style($style_directories = array('styles'))
{
$this->names = $this->get_user_style();
$paths = array();
foreach ($names as $name)
foreach ($style_directories as $directory)
{
$paths[] = $this->get_style_path($name);
foreach ($this->names as $name)
{
$path = $this->get_style_path($name, $directory);
if (is_dir($path))
{
$paths[] = $path;
}
}
}
return $this->set_custom_style($style_path, $paths, $names);
$this->provider->set_styles($paths);
$this->locator->set_paths($this->provider);
$new_paths = array();
foreach ($paths as $path)
{
$new_paths[] = $path . '/template/';
}
$this->template->set_style_names($this->names, $new_paths, ($style_directories === array('styles')));
return true;
}
/**
@ -118,6 +152,7 @@ class phpbb_style
* @param array or string $paths Array of style paths, relative to current root directory
* @param array $names Array of names of templates in inheritance tree order, used by extensions. If empty, $name will be used.
* @param string $template_path Path to templates, relative to style directory. False if path should be set to default (templates/).
* @return bool true
*/
public function set_custom_style($name, $paths, $names = array(), $template_path = false)
{
@ -135,18 +170,18 @@ class phpbb_style
$this->provider->set_styles($paths);
$this->locator->set_paths($this->provider);
$this->template->set_style_names($names);
if ($template_path !== false)
{
$this->locator->set_template_path($template_path);
}
else
$new_paths = array();
foreach ($paths as $path)
{
$this->locator->set_default_template_path();
$new_paths[] = $path . '/' . (($template_path !== false) ? $template_path : 'template/');
}
$this->template->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $name) . '_';
$this->template->set_style_names($names, $new_paths);
return true;
}
@ -155,11 +190,14 @@ class phpbb_style
* Get location of style directory for specific style_path
*
* @param string $path Style path, such as "prosilver"
* @param string $style_base_directory The base directory the style is in
* E.g. 'styles', 'ext/foo/bar/styles'
* Default: 'styles'
* @return string Path to style directory, relative to current path
*/
public function get_style_path($path)
public function get_style_path($path, $style_base_directory = 'styles')
{
return $this->phpbb_root_path . 'styles/' . $path;
return $this->phpbb_root_path . trim($style_base_directory, '/') . '/' . $path;
}
/**

View file

@ -1,166 +0,0 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
stream_filter_register('phpbb_template', 'phpbb_template_filter');
/**
* Extension of template class - Functions needed for compiling templates only.
*
* @package phpBB3
* @uses template_filter As a PHP stream filter to perform compilation of templates
*/
class phpbb_template_compile
{
/**
* Array of parameters to forward to template filter
*
* @var array
*/
private $filter_params;
/**
* Array of default parameters
*
* @var array
*/
private $default_filter_params;
/**
* Constructor.
*
* @param bool $allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag)
* @param array $style_names Name of style to which the template being compiled belongs and parents in style tree order
* @param phpbb_style_resource_locator $locator Resource locator
* @param string $phpbb_root_path Path to phpBB root directory
* @param phpbb_extension_manager $extension_manager Extension manager to use for finding template fragments in extensions; if null, template events will not be invoked
* @param phpbb_user $user Current user
*/
public function __construct($allow_php, $style_names, $locator, $phpbb_root_path, $extension_manager = null, $user = null)
{
$this->filter_params = $this->default_filter_params = array(
'allow_php' => $allow_php,
'style_names' => $style_names,
'locator' => $locator,
'phpbb_root_path' => $phpbb_root_path,
'extension_manager' => $extension_manager,
'user' => $user,
'template_compile' => $this,
'cleanup' => true,
);
}
/**
* Set filter parameters
*
* @param array $params Array of parameters (will be merged onto $this->filter_params)
*/
public function set_filter_params($params)
{
$this->filter_params = array_merge(
$this->filter_params,
$params
);
}
/**
* Reset filter parameters to their default settings
*/
public function reset_filter_params()
{
$this->filter_params = $this->default_filter_params;
}
/**
* Compiles template in $source_file and writes compiled template to
* cache directory
*
* @param string $handle Template handle to compile
* @param string $source_file Source template file
* @return bool Return true on success otherwise false
*/
public function compile_file_to_file($source_file, $compiled_file)
{
$lock = new phpbb_lock_flock($compiled_file);
$lock->acquire();
$source_handle = @fopen($source_file, 'rb');
$destination_handle = @fopen($compiled_file, 'wb');
if (!$source_handle || !$destination_handle)
{
return false;
}
$this->compile_stream_to_stream($source_handle, $destination_handle);
@fclose($source_handle);
@fclose($destination_handle);
phpbb_chmod($compiled_file, CHMOD_READ | CHMOD_WRITE);
$lock->release();
clearstatcache();
return true;
}
/**
* Compiles a template located at $source_file.
*
* Returns PHP source suitable for eval().
*
* @param string $source_file Source template file
* @return string|bool Return compiled code on successful compilation otherwise false
*/
public function compile_file($source_file)
{
$source_handle = @fopen($source_file, 'rb');
$destination_handle = @fopen('php://temp' ,'r+b');
if (!$source_handle || !$destination_handle)
{
return false;
}
$this->compile_stream_to_stream($source_handle, $destination_handle);
@fclose($source_handle);
rewind($destination_handle);
$contents = stream_get_contents($destination_handle);
@fclose($dest_handle);
return $contents;
}
/**
* Compiles contents of $source_stream into $dest_stream.
*
* A stream filter is appended to $source_stream as part of the
* process.
*
* @param resource $source_stream Source stream
* @param resource $dest_stream Destination stream
* @return null
*/
private function compile_stream_to_stream($source_stream, $dest_stream)
{
stream_filter_append($source_stream, 'phpbb_template', null, $this->filter_params);
stream_copy_to_stream($source_stream, $dest_stream);
}
}

View file

@ -138,7 +138,7 @@ class phpbb_template_context
}
$s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0;
$vararray['S_ROW_COUNT'] = $s_row_count;
$vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count;
// Assign S_FIRST_ROW
if (!$s_row_count)
@ -146,6 +146,9 @@ class phpbb_template_context
$vararray['S_FIRST_ROW'] = true;
}
// Assign S_BLOCK_NAME
$vararray['S_BLOCK_NAME'] = $blocks[$blockcount];
// Now the tricky part, we always assign S_LAST_ROW and remove the entry before
// This is much more clever than going through the complete template data on display (phew)
$vararray['S_LAST_ROW'] = true;
@ -158,12 +161,18 @@ class phpbb_template_context
// We're adding a new iteration to this block with the given
// variable assignments.
$str[$blocks[$blockcount]][] = $vararray;
// Set S_NUM_ROWS
foreach ($str[$blocks[$blockcount]] as &$mod_block)
{
$mod_block['S_NUM_ROWS'] = sizeof($str[$blocks[$blockcount]]);
}
}
else
{
// Top-level block.
$s_row_count = (isset($this->tpldata[$blockname])) ? sizeof($this->tpldata[$blockname]) : 0;
$vararray['S_ROW_COUNT'] = $s_row_count;
$vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count;
// Assign S_FIRST_ROW
if (!$s_row_count)
@ -171,6 +180,9 @@ class phpbb_template_context
$vararray['S_FIRST_ROW'] = true;
}
// Assign S_BLOCK_NAME
$vararray['S_BLOCK_NAME'] = $blockname;
// We always assign S_LAST_ROW and remove the entry before
$vararray['S_LAST_ROW'] = true;
if ($s_row_count > 0)
@ -180,6 +192,12 @@ class phpbb_template_context
// Add a new iteration to this block with the variable assignments we were given.
$this->tpldata[$blockname][] = $vararray;
// Set S_NUM_ROWS
foreach ($this->tpldata[$blockname] as &$mod_block)
{
$mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]);
}
}
return true;
@ -298,14 +316,26 @@ class phpbb_template_context
$vararray['S_FIRST_ROW'] = true;
}
// Assign S_BLOCK_NAME
$vararray['S_BLOCK_NAME'] = $blockname;
// Re-position template blocks
for ($i = sizeof($block); $i > $key; $i--)
{
$block[$i] = $block[$i-1];
$block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i;
}
// Insert vararray at given position
$block[$key] = $vararray;
$block[$key]['S_ROW_COUNT'] = $block[$key]['S_ROW_NUM'] = $key;
// Set S_NUM_ROWS
foreach ($this->tpldata[$blockname] as &$mod_block)
{
$mod_block['S_NUM_ROWS'] = sizeof($this->tpldata[$blockname]);
}
return true;
}

File diff suppressed because it is too large Load diff

View file

@ -1,35 +0,0 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Template renderer interface.
*
* Objects implementing this interface encapsulate a means of displaying
* a template.
*
* @package phpBB3
*/
interface phpbb_template_renderer
{
/**
* Displays the template managed by this renderer.
*
* @param phpbb_template_context $context Template context to use
* @param array $lang Language entries to use
*/
public function render($context, $lang);
}

View file

@ -1,60 +0,0 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Template renderer that stores compiled template's php code and
* displays it via eval.
*
* @package phpBB3
*/
class phpbb_template_renderer_eval implements phpbb_template_renderer
{
/**
* Template code to be eval'ed.
*/
private $code;
/**
* Constructor. Stores provided code for future evaluation.
* Template includes are delegated to template object $template.
*
* @param string $code php code of the template
* @param phpbb_template $template template object
*/
public function __construct($code, $template)
{
$this->code = $code;
$this->template = $template;
}
/**
* Displays the template managed by this renderer by eval'ing php code
* of the template.
*
* @param phpbb_template_context $context Template context to use
* @param array $lang Language entries to use
*/
public function render($context, $lang)
{
$_template = $this->template;
$_tpldata = &$context->get_data_ref();
$_rootref = &$context->get_root_ref();
$_lang = $lang;
eval(' ?>' . $this->code . '<?php ');
}
}

View file

@ -1,60 +0,0 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Template renderer that stores path to php file with template code
* and displays it by including the file.
*
* @package phpBB3
*/
class phpbb_template_renderer_include implements phpbb_template_renderer
{
/**
* Template path to be included.
*/
private $path;
/**
* Constructor. Stores path to the template for future inclusion.
* Template includes are delegated to template object $template.
*
* @param string $path path to the template
*/
public function __construct($path, $template)
{
$this->path = $path;
$this->template = $template;
}
/**
* Displays the template managed by this renderer by including
* the php file containing the template.
*
* @param phpbb_template_context $context Template context to use
* @param array $lang Language entries to use
*/
public function render($context, $lang)
{
$_template = $this->template;
$_tpldata = &$context->get_data_ref();
$_rootref = &$context->get_root_ref();
$_lang = $lang;
include($this->path);
}
}

View file

@ -2,7 +2,7 @@
/**
*
* @package phpBB3
* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@ -15,143 +15,48 @@ if (!defined('IN_PHPBB'))
exit;
}
/**
* @todo
* IMG_ for image substitution?
* {IMG_[key]:[alt]:[type]}
* {IMG_ICON_CONTACT:CONTACT:full} -> $user->img('icon_contact', 'CONTACT', 'full');
*
* More in-depth...
* yadayada
*/
/**
* Base Template class.
* @package phpBB3
*/
class phpbb_template
interface phpbb_template
{
/**
* Template context.
* Stores template data used during template rendering.
* @var phpbb_template_context
*/
private $context;
/**
* Path of the cache directory for the template
* @var string
*/
public $cachepath = '';
/**
* phpBB root path
* @var string
*/
private $phpbb_root_path;
/**
* PHP file extension
* @var string
*/
private $php_ext;
/**
* phpBB config instance
* @var phpbb_config
*/
private $config;
/**
* Current user
* @var phpbb_user
*/
private $user;
/**
* Template locator
* @var phpbb_template_locator
*/
private $locator;
/**
* Extension manager.
* Clear the cache
*
* @var phpbb_extension_manager
* @return phpbb_template
*/
private $extension_manager;
/**
* Name of the style that the template being compiled and/or rendered
* belongs to, and its parents, in inheritance tree order.
*
* Used to invoke style-specific template events.
*
* @var array
*/
private $style_names;
/**
* Constructor.
*
* @param string $phpbb_root_path phpBB root path
* @param user $user current user
* @param phpbb_template_locator $locator template locator
* @param phpbb_template_context $context template context
* @param phpbb_extension_manager $extension_manager extension manager, if null then template events will not be invoked
*/
public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_locator $locator, phpbb_template_context $context, phpbb_extension_manager $extension_manager = null)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->config = $config;
$this->user = $user;
$this->locator = $locator;
$this->context = $context;
$this->extension_manager = $extension_manager;
}
public function clear_cache();
/**
* Sets the template filenames for handles.
*
* @param array $filename_array Should be a hash of handle => filename pairs.
* @return phpbb_template $this
*/
public function set_filenames(array $filename_array)
{
$this->locator->set_filenames($filename_array);
return true;
}
public function set_filenames(array $filename_array);
/**
* Sets the style names corresponding to style hierarchy being compiled
* Sets the style names/paths corresponding to style hierarchy being compiled
* and/or rendered.
*
* @param array $style_names List of style names in inheritance tree order
* @return null
* @param array $style_paths List of style paths in inheritance tree order
* @return phpbb_template $this
*/
public function set_style_names(array $style_names)
{
$this->style_names = $style_names;
}
public function set_style_names(array $style_names, array $style_paths);
/**
* Clears all variables and blocks assigned to this template.
*
* @return phpbb_template $this
*/
public function destroy()
{
$this->context->clear();
}
public function destroy();
/**
* Reset/empty complete block
*
* @param string $blockname Name of block to destroy
* @return phpbb_template $this
*/
public function destroy_block_vars($blockname)
{
$this->context->destroy_block_vars($blockname);
}
public function destroy_block_vars($blockname);
/**
* Display a template for provided handle.
@ -161,81 +66,9 @@ class phpbb_template
* This function calls hooks.
*
* @param string $handle Handle to display
* @return bool True on success, false on failure
* @return phpbb_template $this
*/
public function display($handle)
{
$result = $this->call_hook($handle, __FUNCTION__);
if ($result !== false)
{
return $result[0];
}
return $this->load_and_render($handle);
}
/**
* Loads a template for $handle, compiling it if necessary, and
* renders the template.
*
* @param string $handle Template handle to render
* @return bool True on success, false on failure
*/
private function load_and_render($handle)
{
$renderer = $this->_tpl_load($handle);
if ($renderer)
{
$renderer->render($this->context, $this->get_lang());
return true;
}
else
{
return false;
}
}
/**
* Calls hook if any is defined.
*
* @param string $handle Template handle being displayed.
* @param string $method Method name of the caller.
*/
private function call_hook($handle, $method)
{
global $phpbb_hook;
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, $method), $handle, $this))
{
if ($phpbb_hook->hook_return(array(__CLASS__, $method)))
{
$result = $phpbb_hook->hook_return_result(array(__CLASS__, $method));
return array($result);
}
}
return false;
}
/**
* Obtains language array.
* This is either lang property of $user property, or if
* it is not set an empty array.
* @return array language entries
*/
public function get_lang()
{
if (isset($this->user->lang))
{
$lang = $this->user->lang;
}
else
{
$lang = array();
}
return $lang;
}
public function display($handle);
/**
* Display the handle and assign the output to a template variable
@ -244,118 +77,17 @@ class phpbb_template
* @param string $handle Handle to operate on
* @param string $template_var Template variable to assign compiled handle to
* @param bool $return_content If true return compiled handle, otherwise assign to $template_var
* @return bool|string false on failure, otherwise if $return_content is true return string of the compiled handle, otherwise return true
* @return phpbb_template|string if $return_content is true return string of the compiled handle, otherwise return $this
*/
public function assign_display($handle, $template_var = '', $return_content = true)
{
ob_start();
$result = $this->display($handle);
$contents = ob_get_clean();
if ($result === false)
{
return false;
}
if ($return_content)
{
return $contents;
}
$this->assign_var($template_var, $contents);
return true;
}
/**
* Obtains a template renderer for a template identified by specified
* handle. The template renderer can display the template later.
*
* Template source will first be compiled into php code.
* If template cache is writable the compiled php code will be stored
* on filesystem and template will not be subsequently recompiled.
* If template cache is not writable template source will be recompiled
* every time it is needed. DEBUG define and load_tplcompile
* configuration setting may be used to force templates to be always
* recompiled.
*
* Returns an object implementing phpbb_template_renderer, or null
* if template loading or compilation failed. Call render() on the
* renderer to display the template. This will result in template
* contents sent to the output stream (unless, of course, output
* buffering is in effect).
*
* @param string $handle Handle of the template to load
* @return phpbb_template_renderer Template renderer object, or null on failure
* @uses phpbb_template_compile is used to compile template source
*/
private function _tpl_load($handle)
{
$output_file = $this->_compiled_file_for_handle($handle);
$recompile = defined('DEBUG') ||
!file_exists($output_file) ||
@filesize($output_file) === 0;
if ($recompile || $this->config['load_tplcompile'])
{
// Set only if a recompile or an mtime check are required.
$source_file = $this->locator->get_source_file_for_handle($handle);
if (!$recompile && @filemtime($output_file) < @filemtime($source_file))
{
$recompile = true;
}
}
// Recompile page if the original template is newer, otherwise load the compiled version
if (!$recompile)
{
return new phpbb_template_renderer_include($output_file, $this);
}
$compile = new phpbb_template_compile($this->config['tpl_allow_php'], $this->style_names, $this->locator, $this->phpbb_root_path, $this->extension_manager, $this->user);
if ($compile->compile_file_to_file($source_file, $output_file) !== false)
{
$renderer = new phpbb_template_renderer_include($output_file, $this);
}
else if (($code = $compile->compile_file($source_file)) !== false)
{
$renderer = new phpbb_template_renderer_eval($code, $this);
}
else
{
$renderer = null;
}
return $renderer;
}
/**
* Determines compiled file path for handle $handle.
*
* @param string $handle Template handle (i.e. "friendly" template name)
* @return string Compiled file path
*/
private function _compiled_file_for_handle($handle)
{
$source_file = $this->locator->get_filename_for_handle($handle);
$compiled_file = $this->cachepath . str_replace('/', '.', $source_file) . '.' . $this->php_ext;
return $compiled_file;
}
public function assign_display($handle, $template_var = '', $return_content = true);
/**
* Assign key variable pairs from an array
*
* @param array $vararray A hash of variable name => value pairs
* @return phpbb_template $this
*/
public function assign_vars(array $vararray)
{
foreach ($vararray as $key => $val)
{
$this->assign_var($key, $val);
}
}
public function assign_vars(array $vararray);
/**
* Assign a single scalar value to a single key.
@ -364,11 +96,9 @@ class phpbb_template
*
* @param string $varname Variable name
* @param string $varval Value to assign to variable
* @return phpbb_template $this
*/
public function assign_var($varname, $varval)
{
$this->context->assign_var($varname, $varval);
}
public function assign_var($varname, $varval);
/**
* Append text to the string value stored in a key.
@ -377,24 +107,18 @@ class phpbb_template
*
* @param string $varname Variable name
* @param string $varval Value to append to variable
* @return phpbb_template $this
*/
public function append_var($varname, $varval)
{
$this->context->append_var($varname, $varval);
}
public function append_var($varname, $varval);
// Docstring is copied from phpbb_template_context method with the same name.
/**
* Assign key variable pairs from an array to a specified block
* @param string $blockname Name of block to assign $vararray to
* @param array $vararray A hash of variable name => value pairs
* @return phpbb_template $this
*/
public function assign_block_vars($blockname, array $vararray)
{
return $this->context->assign_block_vars($blockname, $vararray);
}
public function assign_block_vars($blockname, array $vararray);
// Docstring is copied from phpbb_template_context method with the same name.
/**
* Change already assigned key variable pair (one-dimensional - single loop entry)
*
@ -422,94 +146,12 @@ class phpbb_template
*
* @return bool false on error, true on success
*/
public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert')
{
return $this->context->alter_block_array($blockname, $vararray, $key, $mode);
}
public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert');
/**
* Include a separate template.
* Get path to template for handle (required for BBCode parser)
*
* This function is marked public due to the way the template
* implementation uses it. It is actually an implementation function
* and should not be considered part of template class's public API.
*
* @param string $filename Template filename to include
* @param bool $include True to include the file, false to just load it
* @uses template_compile is used to compile uncached templates
* @return string
*/
public function _tpl_include($filename, $include = true)
{
$this->locator->set_filenames(array($filename => $filename));
if (!$this->load_and_render($filename))
{
// trigger_error cannot be used here, as the output already started
echo 'template->_tpl_include(): Failed including ' . htmlspecialchars($handle) . "\n";
}
}
/**
* Include a PHP file.
*
* If a relative path is passed in $filename, it is considered to be
* relative to board root ($phpbb_root_path). Absolute paths are
* also allowed.
*
* This function is marked public due to the way the template
* implementation uses it. It is actually an implementation function
* and should not be considered part of template class's public API.
*
* @param string $filename Path to PHP file to include
*/
public function _php_include($filename)
{
if (phpbb_is_absolute($filename))
{
$file = $filename;
}
else
{
$file = $this->phpbb_root_path . $filename;
}
if (!file_exists($file))
{
// trigger_error cannot be used here, as the output already started
echo 'template->_php_include(): File ' . htmlspecialchars($file) . " does not exist\n";
return;
}
include($file);
}
/**
* Include JS file
*
* @param string $file file name
* @param bool $locate True if file needs to be located
* @param bool $relative True if path is relative to phpBB root directory. Ignored if $locate == true
*/
public function _js_include($file, $locate = false, $relative = false)
{
// Locate file
if ($locate)
{
$located = $this->locator->get_first_file_location(array($file), false, true);
if ($located)
{
$file = $located;
}
}
else if ($relative)
{
$file = $this->phpbb_root_path . $file;
}
$file .= (strpos($file, '?') === false) ? '?' : '&';
$file .= 'assets_version=' . $this->config['assets_version'];
// Add HTML code
$code = '<script src="' . htmlspecialchars($file) . '"></script>';
$this->context->append_var('SCRIPTS', $code);
}
public function get_source_file_for_handle($handle);
}

View file

@ -0,0 +1,69 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* This class holds all DEFINE variables from the current page load
*/
class phpbb_template_twig_definition
{
/** @var array **/
protected $definitions = array();
/**
* Get a DEFINE'd variable
*
* @param string $name
* @return mixed Null if not found
*/
public function __call($name, $arguments)
{
return (isset($this->definitions[$name])) ? $this->definitions[$name] : null;
}
/**
* DEFINE a variable
*
* @param string $name
* @param mixed $value
* @return phpbb_template_twig_definition
*/
public function set($name, $value)
{
$this->definitions[$name] = $value;
return $this;
}
/**
* Append to a variable
*
* @param string $name
* @param string $value
* @return phpbb_template_twig_definition
*/
public function append($name, $value)
{
if (!isset($this->definitions[$name]))
{
$this->definitions[$name] = '';
}
$this->definitions[$name] .= $value;
return $this;
}
}

View file

@ -0,0 +1,140 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_environment extends Twig_Environment
{
/** @var array */
protected $phpbb_extensions;
/** @var phpbb_config */
protected $phpbb_config;
/** @var string */
protected $phpbb_root_path;
/** @var array **/
protected $namespace_look_up_order = array('__main__');
/**
* Constructor
*
* @param phpbb_config $phpbb_config
* @param array $phpbb_extensions Array of enabled extensions (name => path)
* @param string $phpbb_root_path
* @param Twig_LoaderInterface $loader
* @param array $options Array of options to pass to Twig
*/
public function __construct($phpbb_config, $phpbb_extensions, $phpbb_root_path, Twig_LoaderInterface $loader = null, $options = array())
{
$this->phpbb_config = $phpbb_config;
$this->phpbb_extensions = $phpbb_extensions;
$this->phpbb_root_path = $phpbb_root_path;
return parent::__construct($loader, $options);
}
/**
* Get the list of enabled phpBB extensions
*
* Used in EVENT node
*
* @return array
*/
public function get_phpbb_extensions()
{
return $this->phpbb_extensions;
}
/**
* Get phpBB config
*
* @return phpbb_config
*/
public function get_phpbb_config()
{
return $this->phpbb_config;
}
/**
* Get the phpBB root path
*
* @return string
*/
public function get_phpbb_root_path()
{
return $this->phpbb_root_path;
}
/**
* Get the namespace look up order
*
* @return array
*/
public function getNamespaceLookUpOrder()
{
return $this->namespace_look_up_order;
}
/**
* Set the namespace look up order to load templates from
*
* @param array $namespace
* @return Twig_Environment
*/
public function setNamespaceLookUpOrder($namespace)
{
$this->namespace_look_up_order = $namespace;
return $this;
}
/**
* Loads a template by name.
*
* @param string $name The template name
* @param integer $index The index if it is an embedded template
* @return Twig_TemplateInterface A template instance representing the given template name
*/
public function loadTemplate($name, $index = null)
{
if (strpos($name, '@') === false)
{
foreach ($this->getNamespaceLookUpOrder() as $namespace)
{
try
{
if ($namespace === '__main__')
{
return parent::loadTemplate($name, $index);
}
return parent::loadTemplate('@' . $namespace . '/' . $name, $index);
}
catch (Twig_Error_Loader $e)
{
}
}
// We were unable to load any templates
throw $e;
}
else
{
return parent::loadTemplate($name, $index);
}
}
}

View file

@ -0,0 +1,188 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_extension extends Twig_Extension
{
/** @var phpbb_template_context */
protected $context;
/** @var phpbb_user */
protected $user;
/**
* Constructor
*
* @param phpbb_template_context $context
* @param phpbb_user $user
* @return phpbb_template_twig_extension
*/
public function __construct(phpbb_template_context $context, $user)
{
$this->context = $context;
$this->user = $user;
}
/**
* Get the name of this extension
*
* @return string
*/
public function getName()
{
return 'phpbb';
}
/**
* Returns the token parser instance to add to the existing list.
*
* @return array An array of Twig_TokenParser instances
*/
public function getTokenParsers()
{
return array(
new phpbb_template_twig_tokenparser_define,
new phpbb_template_twig_tokenparser_include,
new phpbb_template_twig_tokenparser_includejs,
new phpbb_template_twig_tokenparser_includecss,
new phpbb_template_twig_tokenparser_event,
new phpbb_template_twig_tokenparser_includephp,
new phpbb_template_twig_tokenparser_php,
);
}
/**
* Returns a list of filters to add to the existing list.
*
* @return array An array of filters
*/
public function getFilters()
{
return array(
new Twig_SimpleFilter('subset', array($this, 'loop_subset'), array('needs_environment' => true)),
new Twig_SimpleFilter('addslashes', 'addslashes'),
);
}
/**
* Returns a list of global functions to add to the existing list.
*
* @return array An array of global functions
*/
public function getFunctions()
{
return array(
new Twig_SimpleFunction('lang', array($this, 'lang')),
);
}
/**
* Returns a list of operators to add to the existing list.
*
* @return array An array of operators
*/
public function getOperators()
{
return array(
array(
'!' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
),
array(
// precedence settings are copied from similar operators in Twig core extension
'||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'eq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'ne' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'neq' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'<>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'===' => array('precedence' => 20, 'class' => 'phpbb_template_twig_node_expression_binary_equalequal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'!==' => array('precedence' => 20, 'class' => 'phpbb_template_twig_node_expression_binary_notequalequal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'gt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'gte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'ge' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'lt' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'lte' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'le' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
'mod' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
),
);
}
/**
* Grabs a subset of a loop
*
* @param Twig_Environment $env A Twig_Environment instance
* @param mixed $item A variable
* @param integer $start Start of the subset
* @param integer $end End of the subset
* @param Boolean $preserveKeys Whether to preserve key or not (when the input is an array)
*
* @return mixed The sliced variable
*/
function loop_subset(Twig_Environment $env, $item, $start, $end = null, $preserveKeys = false)
{
// We do almost the same thing as Twig's slice (array_slice), except when $end is positive
if ($end >= 1)
{
// When end is > 1, subset will end on the last item in an array with the specified $end
// This is different from slice in that it is the number we end on rather than the number
// of items to grab (length)
// Start must always be the actual starting number for this calculation (not negative)
$start = ($start < 0) ? sizeof($item) + $start : $start;
$end = $end - $start;
}
// We always include the last element (this was the past design)
$end = ($end == -1 || $end === null) ? null : $end + 1;
return twig_slice($env, $item, $start, $end, $preserveKeys);
}
/**
* Get output for a language variable (L_FOO, LA_FOO)
*
* This function checks to see if the language var was outputted to $context
* (e.g. in the ACP, L_TITLE)
* If not, we return the result of $user->lang()
*
* @param string $lang name
* @return string
*/
function lang()
{
$args = func_get_args();
$key = $args[0];
$context = $this->context->get_data_ref();
$context_vars = $context['.'][0];
if (isset($context_vars['L_' . $key]))
{
return $context_vars['L_' . $key];
}
// LA_ is transformed into lang(\'$1\')|addslashes, so we should not
// need to check for it
return call_user_func_array(array($this->user, 'lang'), $args);
}
}

View file

@ -0,0 +1,300 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_lexer extends Twig_Lexer
{
public function tokenize($code, $filename = null)
{
// Our phpBB tags
// Commented out tokens are handled separately from the main replace
$phpbb_tags = array(
/*'BEGIN',
'BEGINELSE',
'END',
'IF',
'ELSE',
'ELSEIF',
'ENDIF',
'DEFINE',
'UNDEFINE',*/
'ENDDEFINE',
'INCLUDE',
'INCLUDEPHP',
'INCLUDEJS',
'INCLUDECSS',
'PHP',
'ENDPHP',
'EVENT',
);
// Twig tag masks
$twig_tags = array(
'autoescape',
'endautoescape',
'if',
'elseif',
'else',
'endif',
'block',
'endblock',
'use',
'extends',
'embed',
'filter',
'endfilter',
'flush',
'for',
'endfor',
'macro',
'endmacro',
'import',
'from',
'sandbox',
'endsandbox',
'set',
'endset',
'spaceless',
'endspaceless',
'verbatim',
'endverbatim',
);
// Fix tokens that may have inline variables (e.g. <!-- DEFINE $TEST = '{FOO}')
$code = $this->fix_inline_variable_tokens(array(
'DEFINE.+=',
'INCLUDE',
'INCLUDEPHP',
'INCLUDEJS',
'INCLUDECSS',
), $code);
// Fix our BEGIN statements
$code = $this->fix_begin_tokens($code);
// Fix our IF tokens
$code = $this->fix_if_tokens($code);
// Fix our DEFINE tokens
$code = $this->fix_define_tokens($code);
// Replace all of our starting tokens, <!-- TOKEN --> with Twig style, {% TOKEN %}
// This also strips outer parenthesis, <!-- IF (blah) --> becomes <!-- IF blah -->
$code = preg_replace('#<!-- (' . implode('|', $phpbb_tags) . ')(?: (.*?) ?)?-->#', '{% $1 $2 %}', $code);
// Replace all of our twig masks with Twig code (e.g. <!-- BLOCK .+ --> with {% block $1 %})
$code = $this->replace_twig_tag_masks($code, $twig_tags);
// Replace all of our language variables, {L_VARNAME}, with Twig style, {{ lang('NAME') }}
// Appends any filters after lang()
$code = preg_replace('#{L_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2 }}', $code);
// Replace all of our escaped language variables, {LA_VARNAME}, with Twig style, {{ lang('NAME')|addslashes }}
// Appends any filters after lang(), but before addslashes
$code = preg_replace('#{LA_([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ lang(\'$1\')$2|addslashes }}', $code);
// Replace all of our variables, {VARNAME}, with Twig style, {{ VARNAME }}
// Appends any filters
$code = preg_replace('#{([a-zA-Z0-9_\.]+)(\|[^}]+?)?}#', '{{ $1$2 }}', $code);
return parent::tokenize($code, $filename);
}
/**
* Fix tokens that may have inline variables
*
* E.g. <!-- INCLUDE {TEST}.html
*
* @param array $tokens array of tokens to search for (imploded to a regular expression)
* @param string $code
* @return string
*/
protected function fix_inline_variable_tokens($tokens, $code)
{
$callback = function($matches)
{
// Remove any quotes that may have been used in different implementations
// E.g. DEFINE $TEST = 'blah' vs INCLUDE foo
// Replace {} with start/end to parse variables (' ~ TEST ~ '.html)
$matches[2] = str_replace(array('"', "'", '{', '}'), array('', '', "' ~ ", " ~ '"), $matches[2]);
// Surround the matches in single quotes ('' ~ TEST ~ '.html')
return "<!-- {$matches[1]} '{$matches[2]}' -->";
};
return preg_replace_callback('#<!-- (' . implode('|', $tokens) . ') (.+?) -->#', $callback, $code);
}
/**
* Fix begin tokens (convert our BEGIN to Twig for)
*
* Not meant to be used outside of this context, public because the anonymous function calls this
*
* @param string $code
* @param array $parent_nodes (used in recursion)
* @return string
*/
public function fix_begin_tokens($code, $parent_nodes = array())
{
// PHP 5.3 cannot use $this in an anonymous function, so use this as a work-around
$parent_class = $this;
$callback = function ($matches) use ($parent_class, $parent_nodes)
{
$name = $matches[1];
$subset = trim(substr($matches[2], 1, -1)); // Remove parenthesis
$body = $matches[3];
// Is the designer wanting to call another loop in a loop?
// <!-- BEGIN loop -->
// <!-- BEGIN !loop2 -->
// <!-- END !loop2 -->
// <!-- END loop -->
// 'loop2' is actually on the same nesting level as 'loop' you assign
// variables to it with template->assign_block_vars('loop2', array(...))
if (strpos($name, '!') === 0)
{
// Count the number if ! occurrences
$count = substr_count($name, '!');
for ($i = 0; $i < $count; $i++)
{
array_pop($parent_nodes);
$name = substr($name, 1);
}
}
// Remove all parent nodes, e.g. foo, bar from foo.bar.foobar.VAR
foreach ($parent_nodes as $node)
{
$body = preg_replace('#([^a-zA-Z0-9_])' . $node . '\.([a-zA-Z0-9_]+)\.#', '$1$2.', $body);
}
// Add current node to list of parent nodes for child nodes
$parent_nodes[] = $name;
// Recursive...fix any child nodes
$body = $parent_class->fix_begin_tokens($body, $parent_nodes);
// Rename loopname vars (to prevent collisions, loop children are named (loop name)_loop_element)
$body = str_replace($name . '.', $name . '_loop_element.', $body);
// Need the parent variable name
array_pop($parent_nodes);
$parent = (!empty($parent_nodes)) ? end($parent_nodes) . '_loop_element.' : '';
if ($subset !== '')
{
$subset = '|subset(' . $subset . ')';
}
// Turn into a Twig for loop, using (loop name)_loop_element for each child
return "{% for {$name}_loop_element in {$parent}{$name}{$subset} %}{$body}{% endfor %}";
};
// Replace <!-- BEGINELSE --> correctly, only needs to be done once
$code = str_replace('<!-- BEGINELSE -->', '{% else %}', $code);
return preg_replace_callback('#<!-- BEGIN ([!a-zA-Z0-9_]+)(\([0-9,\-]+\))? -->(.+?)<!-- END \1 -->#s', $callback, $code);
}
/**
* Fix IF statements
*
* @param string $code
* @return string
*/
protected function fix_if_tokens($code)
{
$callback = function($matches)
{
// Replace $TEST with definition.TEST
$matches[1] = preg_replace('#\s\$([a-zA-Z_0-9]+)#', ' definition.$1', $matches[1]);
// Replace .test with test|length
$matches[1] = preg_replace('#\s\.([a-zA-Z_0-9\.]+)#', ' $1|length', $matches[1]);
return '<!-- IF' . $matches[1] . '-->';
};
// Replace our "div by" with Twig's divisibleby (Twig does not like test names with spaces)
$code = preg_replace('# div by ([0-9]+)#', ' divisibleby($1)', $code);
return preg_replace_callback('#<!-- IF((.*)[\s][\$|\.|!]([^\s]+)(.*))-->#', $callback, $code);
}
/**
* Fix DEFINE statements and {$VARNAME} variables
*
* @param string $code
* @return string
*/
protected function fix_define_tokens($code)
{
/**
* Changing $VARNAME to definition.varname because set is only local
* context (e.g. DEFINE $TEST will only make $TEST available in current
* template and any child templates, but not any parent templates).
*
* DEFINE handles setting it properly to definition in its node, but the
* variables reading FROM it need to be altered to definition.VARNAME
*
* Setting up definition as a class in the array passed to Twig
* ($context) makes set definition.TEST available in the global context
*/
// Replace <!-- DEFINE $NAME with {% DEFINE definition.NAME
$code = preg_replace('#<!-- DEFINE \$(.*)-->#', '{% DEFINE $1 %}', $code);
// Changing UNDEFINE NAME to DEFINE NAME = null to save from creating an extra token parser/node
$code = preg_replace('#<!-- UNDEFINE \$(.*)-->#', '{% DEFINE $1= null %}', $code);
// Replace all of our variables, {$VARNAME}, with Twig style, {{ definition.VARNAME }}
$code = preg_replace('#{\$([a-zA-Z0-9_\.]+)}#', '{{ definition.$1 }}', $code);
// Replace all of our variables, ~ $VARNAME ~, with Twig style, ~ definition.VARNAME ~
$code = preg_replace('#~ \$([a-zA-Z0-9_\.]+) ~#', '~ definition.$1 ~', $code);
return $code;
}
/**
* Replace Twig tag masks with Twig tag calls
*
* E.g. <!-- BLOCK foo --> with {% block foo %}
*
* @param string $code
* @param array $twig_tags All tags we want to create a mask for
* @return string
*/
protected function replace_twig_tag_masks($code, $twig_tags)
{
$callback = function ($matches)
{
$matches[1] = strtolower($matches[1]);
return "{% {$matches[1]}{$matches[2]}%}";
};
foreach ($twig_tags as &$tag)
{
$tag = strtoupper($tag);
}
// twig_tags is an array of the twig tags, which are all lowercase, but we use all uppercase tags
$code = preg_replace_callback('#<!-- (' . implode('|', $twig_tags) . ')(.*?)-->#',$callback, $code);
return $code;
}
}

View file

@ -0,0 +1,58 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group, sections (c) 2009 Fabien Potencier, Armin Ronacher
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_define extends Twig_Node
{
public function __construct($capture, Twig_NodeInterface $name, Twig_NodeInterface $value, $lineno, $tag = null)
{
parent::__construct(array('name' => $name, 'value' => $value), array('capture' => $capture, 'safe' => false), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
if ($this->getAttribute('capture')) {
$compiler
->write("ob_start();\n")
->subcompile($this->getNode('value'))
;
$compiler->write("\$value = ('' === \$value = ob_get_clean()) ? '' : new Twig_Markup(\$value, \$this->env->getCharset());\n");
}
else
{
$compiler
->write("\$value = ")
->subcompile($this->getNode('value'))
->raw(";\n")
;
}
$compiler
->write("\$context['definition']->set('")
->raw($this->getNode('name')->getAttribute('name'))
->raw("', \$value);\n")
;
}
}

View file

@ -0,0 +1,79 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_event extends Twig_Node
{
/** @var Twig_Environment */
protected $environment;
public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $lineno, $tag = null)
{
$this->environment = $environment;
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$location = $this->getNode('expr')->getAttribute('name');
foreach ($this->environment->get_phpbb_extensions() as $ext_namespace => $ext_path)
{
$ext_namespace = str_replace('/', '_', $ext_namespace);
if (defined('DEBUG'))
{
// If debug mode is enabled, lets check for new/removed EVENT
// templates on page load rather than at compile. This is
// slower, but makes developing extensions easier (no need to
// purge the cache when a new event template file is added)
$compiler
->write("if (\$this->env->getLoader()->exists('@{$ext_namespace}/{$location}.html')) {\n")
->indent()
;
}
if (defined('DEBUG') || $this->environment->getLoader()->exists('@' . $ext_namespace . '/' . $location . '.html'))
{
$compiler
->write("\$previous_look_up_order = \$this->env->getNamespaceLookUpOrder();\n")
// We set the namespace lookup order to be this extension first, then the main path
->write("\$this->env->setNamespaceLookUpOrder(array('{$ext_namespace}', '__main__'));\n")
->write("\$this->env->loadTemplate('@{$ext_namespace}/{$location}.html')->display(\$context);\n")
->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n")
;
}
if (defined('DEBUG'))
{
$compiler
->outdent()
->write("}\n\n")
;
}
}
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_expression_binary_equalequal extends Twig_Node_Expression_Binary
{
public function operator(Twig_Compiler $compiler)
{
return $compiler->raw('===');
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_expression_binary_notequalequal extends Twig_Node_Expression_Binary
{
public function operator(Twig_Compiler $compiler)
{
return $compiler->raw('!==');
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_include extends Twig_Node_Include
{
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$compiler
->write("\$location = ")
->subcompile($this->getNode('expr'))
->raw(";\n")
->write("\$namespace = false;\n")
->write("if (strpos(\$location, '@') === 0) {\n")
->indent()
->write("\$namespace = substr(\$location, 1, strpos(\$location, '/') - 1);\n")
->write("\$previous_look_up_order = \$this->env->getNamespaceLookUpOrder();\n")
// We set the namespace lookup order to be this namespace first, then the main path
->write("\$this->env->setNamespaceLookUpOrder(array(\$namespace, '__main__'));\n")
->outdent()
->write("}\n")
;
parent::compile($compiler);
$compiler
->write("if (\$namespace) {\n")
->indent()
->write("\$this->env->setNamespaceLookUpOrder(\$previous_look_up_order);\n")
->outdent()
->write("}\n")
;
}
}

View file

@ -0,0 +1,65 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_template_twig_node_includeasset extends Twig_Node
{
/** @var Twig_Environment */
protected $environment;
public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $lineno, $tag = null)
{
$this->environment = $environment;
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$config = $this->environment->get_phpbb_config();
$compiler
->write("\$asset_file = ")
->subcompile($this->getNode('expr'))
->raw(";\n")
->write("\$argument_string = \$anchor_string = '';\n")
->write("if ((\$argument_string_start = strpos(\$asset_file, '?')) !== false) {\n")
->indent()
->write("\$argument_string = substr(\$asset_file, \$argument_string_start);\n")
->write("\$asset_file = substr(\$asset_file, 0, \$argument_string_start);\n")
->write("if ((\$anchor_string_start = strpos(\$argument_string, '#')) !== false) {\n")
->indent()
->write("\$anchor_string = substr(\$argument_string, \$anchor_string_start);\n")
->write("\$argument_string = substr(\$argument_string, 0, \$anchor_string_start);\n")
->outdent()
->write("}\n")
->outdent()
->write("}\n")
->write("if (strpos(\$asset_file, '//') !== 0 && strpos(\$asset_file, 'http://') !== 0 && strpos(\$asset_file, 'https://') !== 0 && !file_exists(\$asset_file)) {\n")
->indent()
->write("\$asset_file = \$this->getEnvironment()->getLoader()->getCacheKey(\$asset_file);\n")
->write("\$argument_string .= ((\$argument_string) ? '&' : '?') . 'assets_version={$config['assets_version']}';\n")
->outdent()
->write("}\n")
->write("\$asset_file .= \$argument_string . \$anchor_string;\n")
->write("\$context['definition']->append('{$this->get_definition_name()}', '")
;
$this->append_asset($compiler);
$compiler
->raw("\n');\n")
;
}
}

View file

@ -0,0 +1,30 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_template_twig_node_includecss extends phpbb_template_twig_node_includeasset
{
public function get_definition_name()
{
return 'STYLESHEETS';
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function append_asset(Twig_Compiler $compiler)
{
$compiler
->raw("<link href=\"' . ")
->raw("\$asset_file . '\"")
->raw(' rel="stylesheet" type="text/css" media="screen, projection" />')
;
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_template_twig_node_includejs extends phpbb_template_twig_node_includeasset
{
public function get_definition_name()
{
return 'SCRIPTS';
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
protected function append_asset(Twig_Compiler $compiler)
{
$config = $this->environment->get_phpbb_config();
$compiler
->raw("<script type=\"text/javascript\" src=\"' . ")
->raw("\$asset_file")
->raw(". '\"></script>\n")
;
}
}

View file

@ -0,0 +1,91 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group, sections (c) 2009 Fabien Potencier, Armin Ronacher
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_includephp extends Twig_Node
{
/** @var Twig_Environment */
protected $environment;
public function __construct(Twig_Node_Expression $expr, phpbb_template_twig_environment $environment, $ignoreMissing = false, $lineno, $tag = null)
{
$this->environment = $environment;
parent::__construct(array('expr' => $expr), array('ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$config = $this->environment->get_phpbb_config();
if (!$config['tpl_allow_php'])
{
$compiler
->write("// INCLUDEPHP Disabled\n")
;
return;
}
if ($this->getAttribute('ignore_missing')) {
$compiler
->write("try {\n")
->indent()
;
}
$compiler
->write("\$location = ")
->subcompile($this->getNode('expr'))
->raw(";\n")
->write("if (phpbb_is_absolute(\$location)) {\n")
->indent()
// Absolute path specified
->write("require(\$location);\n")
->outdent()
->write("} else if (file_exists(\$this->getEnvironment()->get_phpbb_root_path() . \$location)) {\n")
->indent()
// PHP file relative to phpbb_root_path
->write("require(\$this->getEnvironment()->get_phpbb_root_path() . \$location);\n")
->outdent()
->write("} else {\n")
->indent()
// Local path (behaves like INCLUDE)
->write("require(\$this->getEnvironment()->getLoader()->getCacheKey(\$location));\n")
->outdent()
->write("}\n")
;
if ($this->getAttribute('ignore_missing')) {
$compiler
->outdent()
->write("} catch (Twig_Error_Loader \$e) {\n")
->indent()
->write("// ignore missing template\n")
->outdent()
->write("}\n\n")
;
}
}
}

View file

@ -0,0 +1,55 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_node_php extends Twig_Node
{
/** @var Twig_Environment */
protected $environment;
public function __construct(Twig_Node_Text $text, phpbb_template_twig_environment $environment, $lineno, $tag = null)
{
$this->environment = $environment;
parent::__construct(array('text' => $text), array(), $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Twig_Compiler A Twig_Compiler instance
*/
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$config = $this->environment->get_phpbb_config();
if (!$config['tpl_allow_php'])
{
$compiler
->write("// PHP Disabled\n")
;
return;
}
$compiler
->raw($this->getNode('text')->getAttribute('data'))
;
}
}

View file

@ -0,0 +1,66 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group, sections (c) 2009 Fabien Potencier
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_tokenparser_define extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$name = $this->parser->getExpressionParser()->parseExpression();
$capture = false;
if ($stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
$stream->next();
$value = $this->parser->getExpressionParser()->parseExpression();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
} else {
$capture = true;
$stream->expect(Twig_Token::BLOCK_END_TYPE);
$value = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
$stream->expect(Twig_Token::BLOCK_END_TYPE);
}
return new phpbb_template_twig_node_define($capture, $name, $value, $lineno, $this->getTag());
}
public function decideBlockEnd(Twig_Token $token)
{
return $token->test('ENDDEFINE');
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'DEFINE';
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_tokenparser_event extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$expr = $this->parser->getExpressionParser()->parseExpression();
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new phpbb_template_twig_node_event($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'EVENT';
}
}

View file

@ -0,0 +1,46 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group, sections (c) 2009 Fabien Potencier
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_tokenparser_include extends Twig_TokenParser_Include
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$expr = $this->parser->getExpressionParser()->parseExpression();
list($variables, $only, $ignoreMissing) = $this->parseArguments();
return new phpbb_template_twig_node_include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'INCLUDE';
}
}

View file

@ -0,0 +1,38 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_template_twig_tokenparser_includecss extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$expr = $this->parser->getExpressionParser()->parseExpression();
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new phpbb_template_twig_node_includecss($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'INCLUDECSS';
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_tokenparser_includejs extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$expr = $this->parser->getExpressionParser()->parseExpression();
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new phpbb_template_twig_node_includejs($expr, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'INCLUDEJS';
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group, sections (c) 2009 Fabien Potencier, Armin Ronacher
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_tokenparser_includephp extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$expr = $this->parser->getExpressionParser()->parseExpression();
$stream = $this->parser->getStream();
$ignoreMissing = false;
if ($stream->test(Twig_Token::NAME_TYPE, 'ignore')) {
$stream->next();
$stream->expect(Twig_Token::NAME_TYPE, 'missing');
$ignoreMissing = true;
}
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new phpbb_template_twig_node_includephp($expr, $this->parser->getEnvironment(), $ignoreMissing, $token->getLine(), $this->getTag());
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'INCLUDEPHP';
}
}

View file

@ -0,0 +1,55 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class phpbb_template_twig_tokenparser_php extends Twig_TokenParser
{
/**
* Parses a token and returns a node.
*
* @param Twig_Token $token A Twig_Token instance
*
* @return Twig_NodeInterface A Twig_NodeInterface instance
*/
public function parse(Twig_Token $token)
{
$stream = $this->parser->getStream();
$stream->expect(Twig_Token::BLOCK_END_TYPE);
$body = $this->parser->subparse(array($this, 'decideEnd'), true);
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return new phpbb_template_twig_node_php($body, $this->parser->getEnvironment(), $token->getLine(), $this->getTag());
}
public function decideEnd(Twig_Token $token)
{
return $token->test('ENDPHP');
}
/**
* Gets the tag name associated with this token parser.
*
* @return string The tag name
*/
public function getTag()
{
return 'PHP';
}
}

View file

@ -0,0 +1,465 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Twig Template class.
* @package phpBB3
*/
class phpbb_template_twig implements phpbb_template
{
/**
* Template context.
* Stores template data used during template rendering.
* @var phpbb_template_context
*/
protected $context;
/**
* Path of the cache directory for the template
*
* Cannot be changed during runtime.
*
* @var string
*/
private $cachepath = '';
/**
* phpBB root path
* @var string
*/
protected $phpbb_root_path;
/**
* adm relative path
* @var string
*/
protected $adm_relative_path;
/**
* PHP file extension
* @var string
*/
protected $php_ext;
/**
* phpBB config instance
* @var phpbb_config
*/
protected $config;
/**
* Current user
* @var phpbb_user
*/
protected $user;
/**
* Extension manager.
*
* @var phpbb_extension_manager
*/
protected $extension_manager;
/**
* Name of the style that the template being compiled and/or rendered
* belongs to, and its parents, in inheritance tree order.
*
* Used to invoke style-specific template events.
*
* @var array
*/
protected $style_names;
/**
* Twig Environment
*
* @var Twig_Environment
*/
protected $twig;
/**
* Array of filenames assigned to set_filenames
*
* @var array
*/
protected $filenames = array();
/**
* Constructor.
*
* @param string $phpbb_root_path phpBB root path
* @param string $php_ext php extension (typically 'php')
* @param phpbb_config $config
* @param phpbb_user $user
* @param phpbb_template_context $context template context
* @param phpbb_extension_manager $extension_manager extension manager, if null then template events will not be invoked
* @param string $adm_relative_path relative path to adm directory
*/
public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_context $context, phpbb_extension_manager $extension_manager = null, $adm_relative_path = null)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->adm_relative_path = $adm_relative_path;
$this->php_ext = $php_ext;
$this->config = $config;
$this->user = $user;
$this->context = $context;
$this->extension_manager = $extension_manager;
$this->cachepath = $phpbb_root_path . 'cache/twig/';
// Initiate the loader, __main__ namespace paths will be setup later in set_style_names()
$loader = new Twig_Loader_Filesystem('');
$this->twig = new phpbb_template_twig_environment(
$this->config,
($this->extension_manager) ? $this->extension_manager->all_enabled() : array(),
$this->phpbb_root_path,
$loader,
array(
'cache' => (defined('IN_INSTALL')) ? false : $this->cachepath,
'debug' => defined('DEBUG'),
'auto_reload' => (bool) $this->config['load_tplcompile'],
'autoescape' => false,
)
);
$this->twig->addExtension(
new phpbb_template_twig_extension(
$this->context,
$this->user
)
);
$lexer = new phpbb_template_twig_lexer($this->twig);
$this->twig->setLexer($lexer);
}
/**
* Clear the cache
*
* @return phpbb_template
*/
public function clear_cache()
{
if (is_dir($this->cachepath))
{
$this->twig->clearCacheFiles();
}
return $this;
}
/**
* Sets the template filenames for handles.
*
* @param array $filename_array Should be a hash of handle => filename pairs.
* @return phpbb_template $this
*/
public function set_filenames(array $filename_array)
{
$this->filenames = array_merge($this->filenames, $filename_array);
return $this;
}
/**
* Sets the style names/paths corresponding to style hierarchy being compiled
* and/or rendered.
*
* @param array $style_names List of style names in inheritance tree order
* @param array $style_paths List of style paths in inheritance tree order
* @param bool $is_core True if the style names are the "core" styles for this page load
* Core means the main phpBB template files
* @return phpbb_template $this
*/
public function set_style_names(array $style_names, array $style_paths, $is_core = false)
{
$this->style_names = $style_names;
// Set as __main__ namespace
$this->twig->getLoader()->setPaths($style_paths);
// Core style namespace from phpbb_style::set_style()
if ($is_core)
{
$this->twig->getLoader()->setPaths($style_paths, 'core');
}
// Add admin namespace
if (is_dir($this->phpbb_root_path . $this->adm_relative_path . 'style/'))
{
$this->twig->getLoader()->setPaths($this->phpbb_root_path . $this->adm_relative_path . 'style/', 'admin');
}
// Add all namespaces for all extensions
if ($this->extension_manager instanceof phpbb_extension_manager)
{
$style_names[] = 'all';
foreach ($this->extension_manager->all_enabled() as $ext_namespace => $ext_path)
{
// namespaces cannot contain /
$namespace = str_replace('/', '_', $ext_namespace);
$paths = array();
foreach ($style_names as $style_name)
{
$ext_style_path = $ext_path . 'styles/' . $style_name . '/template';
if (is_dir($ext_style_path))
{
$paths[] = $ext_style_path;
}
}
$this->twig->getLoader()->setPaths($paths, $namespace);
}
}
return $this;
}
/**
* Clears all variables and blocks assigned to this template.
*
* @return phpbb_template $this
*/
public function destroy()
{
$this->context = array();
return $this;
}
/**
* Reset/empty complete block
*
* @param string $blockname Name of block to destroy
* @return phpbb_template $this
*/
public function destroy_block_vars($blockname)
{
$this->context->destroy_block_vars($blockname);
return $this;
}
/**
* Display a template for provided handle.
*
* The template will be loaded and compiled, if necessary, first.
*
* This function calls hooks.
*
* @param string $handle Handle to display
* @return phpbb_template $this
*/
public function display($handle)
{
$result = $this->call_hook($handle, __FUNCTION__);
if ($result !== false)
{
return $result[0];
}
$this->twig->display($this->get_filename_from_handle($handle), $this->get_template_vars());
return $this;
}
/**
* Calls hook if any is defined.
*
* @param string $handle Template handle being displayed.
* @param string $method Method name of the caller.
*/
protected function call_hook($handle, $method)
{
global $phpbb_hook;
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, $method), $handle, $this))
{
if ($phpbb_hook->hook_return(array(__CLASS__, $method)))
{
$result = $phpbb_hook->hook_return_result(array(__CLASS__, $method));
return array($result);
}
}
return false;
}
/**
* Display the handle and assign the output to a template variable
* or return the compiled result.
*
* @param string $handle Handle to operate on
* @param string $template_var Template variable to assign compiled handle to
* @param bool $return_content If true return compiled handle, otherwise assign to $template_var
* @return phpbb_template|string if $return_content is true return string of the compiled handle, otherwise return $this
*/
public function assign_display($handle, $template_var = '', $return_content = true)
{
if ($return_content)
{
return $this->twig->render($this->get_filename_from_handle($handle), $this->get_template_vars());
}
$this->assign_var($template_var, $this->twig->render($this->get_filename_from_handle($handle, $this->get_template_vars())));
return $this;
}
/**
* Assign key variable pairs from an array
*
* @param array $vararray A hash of variable name => value pairs
* @return phpbb_template $this
*/
public function assign_vars(array $vararray)
{
foreach ($vararray as $key => $val)
{
$this->assign_var($key, $val);
}
return $this;
}
/**
* Assign a single scalar value to a single key.
*
* Value can be a string, an integer or a boolean.
*
* @param string $varname Variable name
* @param string $varval Value to assign to variable
* @return phpbb_template $this
*/
public function assign_var($varname, $varval)
{
$this->context->assign_var($varname, $varval);
return $this;
}
/**
* Append text to the string value stored in a key.
*
* Text is appended using the string concatenation operator (.).
*
* @param string $varname Variable name
* @param string $varval Value to append to variable
* @return phpbb_template $this
*/
public function append_var($varname, $varval)
{
$this->context->append_var($varname, $varval);
return $this;
}
/**
* Assign key variable pairs from an array to a specified block
* @param string $blockname Name of block to assign $vararray to
* @param array $vararray A hash of variable name => value pairs
* @return phpbb_template $this
*/
public function assign_block_vars($blockname, array $vararray)
{
$this->context->assign_block_vars($blockname, $vararray);
return $this;
}
/**
* Change already assigned key variable pair (one-dimensional - single loop entry)
*
* An example of how to use this function:
* {@example alter_block_array.php}
*
* @param string $blockname the blockname, for example 'loop'
* @param array $vararray the var array to insert/add or merge
* @param mixed $key Key to search for
*
* array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position]
*
* int: Position [the position to change or insert at directly given]
*
* If key is false the position is set to 0
* If key is true the position is set to the last entry
*
* @param string $mode Mode to execute (valid modes are 'insert' and 'change')
*
* If insert, the vararray is inserted at the given position (position counting from zero).
* If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value).
*
* Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array)
* and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars)
*
* @return bool false on error, true on success
*/
public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert')
{
return $this->context->alter_block_array($blockname, $vararray, $key, $mode);
}
/**
* Get template vars in a format Twig will use (from the context)
*
* @return array
*/
public function get_template_vars()
{
$context_vars = $this->context->get_data_ref();
$vars = array_merge(
$context_vars['.'][0], // To get normal vars
$context_vars, // To get loops
array(
'definition' => new phpbb_template_twig_definition(),
'user' => $this->user,
)
);
// cleanup
unset($vars['.']);
return $vars;
}
/**
* Get a filename from the handle
*
* @param string $handle
* @return string
*/
protected function get_filename_from_handle($handle)
{
return (isset($this->filenames[$handle])) ? $this->filenames[$handle] : $handle;
}
/**
* Get path to template for handle (required for BBCode parser)
*
* @return string
*/
public function get_source_file_for_handle($handle)
{
return $this->twig->getLoader()->getCacheKey($this->get_filename_from_handle($handle));
}
}

View file

@ -565,7 +565,7 @@ class ucp_groups
if ($colour_error = validate_data($submit_ary, array('colour' => array('hex_colour', true))))
{
// Replace "error" string with its real, localised form
$error = array_merge($error, array_map(array(&$user, 'lang'), $colour_error));
$error = array_merge($error, $colour_error);
}
if (!sizeof($error))
@ -613,6 +613,7 @@ class ucp_groups
if (sizeof($error))
{
$error = array_map(array(&$user, 'lang'), $error);
$group_rank = $submit_ary['rank'];
$group_desc_data = array(

View file

@ -214,7 +214,7 @@ $config = new phpbb_config(array(
$phpbb_style_resource_locator = new phpbb_style_resource_locator();
$phpbb_style_path_provider = new phpbb_style_path_provider();
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $phpbb_style_resource_locator, new phpbb_template_context());
$template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $user, new phpbb_template_context());
$phpbb_style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $phpbb_style_resource_locator, $phpbb_style_path_provider, $template);
$phpbb_style->set_ext_dir_prefix('adm/');
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), '');

View file

@ -606,7 +606,7 @@ $lang = array_merge($lang, array(
'LOG_FORUM_MOVE_UP' => '<strong>Moved forum</strong> %1$s <strong>above</strong> %2$s',
'LOG_FORUM_SYNC' => '<strong>Re-synchronised forum</strong><br />» %s',
'LOG_GENERAL_ERROR' => '<strong>A general error occured</strong>: %1$s <br />» %2$s',
'LOG_GENERAL_ERROR' => '<strong>A general error occurred</strong>: %1$s <br />» %2$s',
'LOG_GROUP_CREATED' => '<strong>New usergroup created</strong><br />» %s',
'LOG_GROUP_DEFAULTS' => '<strong>Group “%1$s” made default for members</strong><br />» %2$s',

View file

@ -83,7 +83,8 @@ $lang = array_merge($lang, array(
'NUMBER' => 'Any series of digits',
'EMAIL' => 'A valid email address',
'URL' => 'A valid URL using any protocol (http, ftp, etc… cannot be used for javascript exploits). If none is given, “http://” is prefixed to the string.',
'LOCAL_URL' => 'A local URL. The URL must be relative to the topic page and cannot contain a server name or protocol.',
'LOCAL_URL' => 'A local URL. The URL must be relative to the topic page and cannot contain a server name or protocol, as links are prefixed with “%s”',
'RELATIVE_URL' => 'A relative URL. You can use this to match parts of a URL, but be careful: a full URL is a valid relative URL. When you want to use relative URLs of your board, use the LOCAL_URL token.',
'COLOR' => 'A HTML colour, can be either in the numeric form <samp>#FF1234</samp> or a <a href="http://www.w3.org/TR/CSS21/syndata.html#value-def-color">CSS colour keyword</a> such as <samp>fuchsia</samp> or <samp>InactiveBorder</samp>'
)
));

View file

@ -204,8 +204,8 @@ $lang = array_merge($lang, array(
'ERR_TEMPLATE_EVENT_LOCATION' => 'The specified template event location <em>[%s]</em> is improperly formatted.',
'ERR_TEMPLATE_COMPILATION' => 'The file could not be compiled: %s',
'ERR_UNABLE_TO_LOGIN' => 'The specified username or password is incorrect.',
'ERR_UNWATCHING' => 'An error occured while trying to unsubscribe.',
'ERR_WATCHING' => 'An error occured while trying to subscribe.',
'ERR_UNWATCHING' => 'An error occurred while trying to unsubscribe.',
'ERR_WATCHING' => 'An error occurred while trying to subscribe.',
'ERR_WRONG_PATH_TO_PHPBB' => 'The phpBB path specified appears to be invalid.',
'ERROR' => 'Error',
'EXPAND_VIEW' => 'Expand view',
@ -338,7 +338,7 @@ $lang = array_merge($lang, array(
'LAST_VISIT' => 'Last visit',
'LDAP_NO_LDAP_EXTENSION' => 'LDAP extension not available.',
'LDAP_NO_SERVER_CONNECTION' => 'Could not connect to LDAP server.',
'LDAP_SEARCH_FAILED' => 'An error occured while searching the LDAP directory.',
'LDAP_SEARCH_FAILED' => 'An error occurred while searching the LDAP directory.',
'LEGEND' => 'Legend',
'LOADING' => 'Loading',
'LOCATION' => 'Location',

View file

@ -364,7 +364,7 @@ $lang = array_merge($lang, array(
'UNAVAILABLE' => 'Unavailable',
'UNWRITABLE' => 'Unwritable',
'UPDATE_TOPICS_POSTED' => 'Generating topics posted information',
'UPDATE_TOPICS_POSTED_ERR' => 'An error occured while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.',
'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.',
'VERIFY_OPTIONS' => 'Verifying conversion options',
'VERSION' => 'Version',

View file

@ -45,7 +45,7 @@ $lang = array_merge($lang, array(
'MIGRATION_NOT_FULFILLABLE' => 'The migration "%1$s" is not fulfillable, missing migration "%2$s".',
'MIGRATION_SCHEMA_DONE' => 'Installed Schema: %s',
'MODULE_ERROR' => 'An error occured while creating a module: %s',
'MODULE_ERROR' => 'An error occurred while creating a module: %s',
'MODULE_INFO_FILE_NOT_EXIST' => 'A required module info file is missing: %2$s',
'MODULE_NOT_EXIST' => 'A required module does not exist: %s',

View file

@ -38,7 +38,7 @@ function insert_single(user)
// ]]>
</script>
<!-- ENDIF -->
<!-- INCLUDEJS template/forum_fn.js -->
<!-- INCLUDEJS forum_fn.js -->
<h2 class="solo">{L_FIND_USERNAME}</h2>
<form method="post" action="{S_MODE_ACTION}" id="search_memberlist">

View file

@ -53,11 +53,13 @@
<script type="text/javascript" src="{T_JQUERY_LINK}"></script>
<!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/forum_fn.js?assets_version={T_ASSETS_VERSION}"></script>
<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script>
<!-- INCLUDEJS template/ajax.js -->
{SCRIPTS}
<!-- INCLUDEJS forum_fn.js -->
<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/core.js -->
<!-- INCLUDEJS ajax.js -->
<!-- EVENT overall_footer_after -->
{$SCRIPTS}
</body>
</html>

View file

@ -76,6 +76,8 @@
<!-- EVENT overall_header_head_append -->
{$STYLESHEETS}
</head>
<body id="phpbb" class="section-{SCRIPT_NAME} {S_CONTENT_DIRECTION}">

View file

@ -52,7 +52,7 @@
// ]]>
</script>
<!-- INCLUDEJS template/editor.js -->
<!-- INCLUDEJS editor.js -->
<!-- IF S_BBCODE_ALLOWED -->
<div id="colour_palette" style="display: none;">

View file

@ -15,6 +15,6 @@
{S_TZ_OPTIONS}
</select>
<!-- INCLUDEJS template/timezone.js -->
<!-- INCLUDEJS timezone.js -->
</dd>
</dl>

View file

@ -47,4 +47,4 @@
</div>
</div>
<!-- INCLUDEJS template/avatars.js -->
<!-- INCLUDEJS avatars.js -->

View file

@ -13,9 +13,11 @@
<script type="text/javascript" src="{T_JQUERY_LINK}"></script>
<!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script>
{SCRIPTS}
<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/core.js -->
<!-- EVENT overall_footer_after -->
{$SCRIPTS}
</body>
</html>

View file

@ -132,6 +132,8 @@ function marklist(id, name, state)
<!-- EVENT overall_header_head_append -->
{$STYLESHEETS}
</head>
<body class="{S_CONTENT_DIRECTION}">

View file

@ -15,6 +15,6 @@
{S_TZ_OPTIONS}
</select>
<!-- INCLUDEJS template/timezone.js -->
<!-- INCLUDEJS timezone.js -->
</td>
</tr>

View file

@ -95,7 +95,7 @@
</tr>
</table>
<!-- INCLUDEJS template/avatars.js -->
<!-- INCLUDEJS avatars.js -->
<!-- ELSEIF S_LIST -->

View file

@ -48,6 +48,6 @@
</tr>
</table>
<!-- INCLUDEJS template/avatars.js -->
<!-- INCLUDEJS avatars.js -->
<!-- INCLUDE ucp_footer.html -->

View file

@ -146,7 +146,14 @@ if ($view && !$post_id)
if (!$row)
{
$user->setup('viewtopic');
$sql = 'SELECT forum_style
FROM ' . FORUMS_TABLE . "
WHERE forum_id = $forum_id";
$result = $db->sql_query($sql);
$forum_style = (int) $db->sql_fetchfield('forum_style');
$db->sql_freeresult($result);
$user->setup('viewtopic', $forum_style);
trigger_error(($view == 'next') ? 'NO_NEWER_TOPICS' : 'NO_OLDER_TOPICS');
}
else

View file

@ -14,6 +14,10 @@
<testsuites>
<testsuite name="phpBB Test Suite">
<directory suffix="_test.php">./tests/</directory>
<exclude>tests/lint_test.php</exclude>
</testsuite>
<testsuite name="phpBB Lint Test">
<file>tests/lint_test.php</file>
</testsuite>
</testsuites>

View file

@ -14,6 +14,10 @@
<testsuites>
<testsuite name="phpBB Test Suite">
<directory suffix="_test.php">./tests/</directory>
<exclude>tests/lint_test.php</exclude>
</testsuite>
<testsuite name="phpBB Lint Test">
<file>tests/lint_test.php</file>
</testsuite>
</testsuites>

View file

@ -14,6 +14,10 @@
<testsuites>
<testsuite name="phpBB Test Suite">
<directory suffix="_test.php">./tests/</directory>
<exclude>tests/lint_test.php</exclude>
</testsuite>
<testsuite name="phpBB Lint Test">
<file>tests/lint_test.php</file>
</testsuite>
</testsuites>

View file

@ -0,0 +1,13 @@
<?php
/**
*
* @package testing
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_auth_provider_acp_board_invalid
{
}

View file

@ -0,0 +1,16 @@
<?php
/**
*
* @package testing
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_auth_provider_acp_board_valid extends phpbb_auth_provider_base
{
public function login($username, $password)
{
return;
}
}

View file

@ -0,0 +1,48 @@
<?php
/**
*
* @package testing
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/acp/acp_board.php';
require_once dirname(__FILE__) . '/auth_provider/invalid.php';
require_once dirname(__FILE__) . '/auth_provider/valid.php';
class phpbb_acp_board_select_auth_method_test extends phpbb_test_case
{
protected $acp_board;
public static function select_auth_method_data()
{
return array(
array('acp_board_valid', '<option value="acp_board_valid" selected="selected">Acp_board_valid</option>'),
array('acp_board_invalid', '<option value="acp_board_valid">Acp_board_valid</option>'),
);
}
public function setUp()
{
parent::setUp();
global $phpbb_container;
$phpbb_container = new phpbb_mock_container_builder();
$phpbb_container->set('auth.provider_collection', array(
'auth.provider.acp_board_valid' => new phpbb_auth_provider_acp_board_valid,
'auth.provider.acp_board_invalid' => new phpbb_auth_provider_acp_board_invalid,
));
$this->acp_board = new acp_board();
}
/**
* @dataProvider select_auth_method_data
*/
public function test_select_auth_method($selected, $expected)
{
$this->assertEquals($expected, $this->acp_board->select_auth_method($selected));
}
}

View file

@ -45,15 +45,17 @@ class phpbb_controller_helper_url_test extends phpbb_test_case
*/
public function test_helper_url($route, $params, $is_amp, $session_id, $expected, $description)
{
global $phpbb_dispatcher;
global $phpbb_dispatcher, $phpbb_root_path, $phpEx;
$phpbb_dispatcher = new phpbb_mock_event_dispatcher;
$this->style_resource_locator = new phpbb_style_resource_locator();
$this->user = $this->getMock('phpbb_user');
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $this->user, $this->style_resource_locator, new phpbb_template_context());
$this->template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $this->user, new phpbb_template_context());
$this->style_resource_locator = new phpbb_style_resource_locator();
$this->style_provider = new phpbb_style_path_provider();
$this->style = new phpbb_style($phpbb_root_path, $phpEx, new phpbb_config(array()), $this->user, $this->style_resource_locator, $this->style_provider, $this->template);
$helper = new phpbb_controller_helper($this->template, $this->user, '', 'php');
$this->assertEquals($helper->url($route, $params, $is_amp, $session_id), $expected);
}
}

View file

@ -18,6 +18,11 @@ class phpbb_dbal_order_lower_test extends phpbb_database_test_case
{
$db = $this->new_dbal();
if (strpos($db->sql_layer, 'mysql') === 0 && version_compare($db->sql_server_info(true, false), '5.6', '>='))
{
$this->markTestSkipped('MySQL 5.6 fails to order things correctly. See also: http://tracker.phpbb.com/browse/PHPBB3-11571 http://bugs.mysql.com/bug.php?id=69005');
}
// http://tracker.phpbb.com/browse/PHPBB3-10507
// Test ORDER BY LOWER(style_name)
$db->sql_return_on_error(true);

View file

@ -40,11 +40,12 @@ class phpbb_di_container_test extends phpbb_test_case
public function test_phpbb_create_compiled_container()
{
$phpbb_root_path = __DIR__ . '/../../phpBB/';
$config_file = __DIR__ . '/fixtures/config.php';
$extensions = array(
new phpbb_di_extension_config(__DIR__ . '/fixtures/config.php'),
new phpbb_di_extension_core($phpbb_root_path),
);
$container = phpbb_create_compiled_container($extensions, array(), $phpbb_root_path, 'php');
$container = phpbb_create_compiled_container($config_file, $extensions, array(), $phpbb_root_path, 'php');
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);
$this->assertTrue($container->isFrozen());

View file

@ -42,12 +42,11 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case
$this->user = new phpbb_user();
$this->table_prefix = 'phpbb_';
$this->template = new phpbb_template(
$this->template = new phpbb_template_twig(
$this->phpbb_root_path,
$this->phpEx,
$this->config,
$this->user,
new phpbb_style_resource_locator(),
new phpbb_template_context()
);

View file

@ -36,6 +36,26 @@ abstract class phpbb_functional_common_groups_test extends phpbb_functional_test
$this->add_lang(array('ucp', 'acp/groups'));
}
// Enable all avatars in the ACP
protected function enable_all_avatars()
{
$this->add_lang('acp/board');
$crawler = self::request('GET', 'adm/index.php?i=board&mode=avatar&sid=' . $this->sid);
// Check the default entries we should have
$this->assertContains($this->lang('ALLOW_REMOTE'), $crawler->text());
$this->assertContains($this->lang('ALLOW_AVATARS'), $crawler->text());
$this->assertContains($this->lang('ALLOW_LOCAL'), $crawler->text());
// Now start setting the needed settings
$form = $crawler->selectButton($this->lang('SUBMIT'))->form();
$form['config[allow_avatar_local]']->select(1);
$form['config[allow_avatar_remote]']->select(1);
$form['config[allow_avatar_remote_upload]']->select(1);
$crawler = self::submit($form);
$this->assertContains($this->lang('CONFIG_UPDATED'), $crawler->text());
}
public function groups_manage_test_data()
{
return array(
@ -60,4 +80,34 @@ abstract class phpbb_functional_common_groups_test extends phpbb_functional_test
$crawler = self::submit($form);
$this->assertContains($this->lang($expected), $crawler->text());
}
public function group_avatar_min_max_data()
{
return array(
array('avatar_driver_upload', 'avatar_upload_url', 'foo', 'AVATAR_URL_INVALID'),
array('avatar_driver_upload', 'avatar_upload_url', 'foobar', 'AVATAR_URL_INVALID'),
array('avatar_driver_upload', 'avatar_upload_url', 'http://www.phpbb.com/' . str_repeat('f', 240) . '.png', 'TOO_LONG'),
array('avatar_driver_remote', 'avatar_remote_url', 'foo', 'AVATAR_URL_INVALID'),
array('avatar_driver_remote', 'avatar_remote_url', 'foobar', 'AVATAR_URL_INVALID'),
array('avatar_driver_remote', 'avatar_remote_url', 'http://www.phpbb.com/' . str_repeat('f', 240) . '.png', 'TOO_LONG'),
);
}
/**
* @dataProvider group_avatar_min_max_data
*/
public function test_group_avatar_min_max($avatar_type, $form_name, $input, $expected)
{
$this->login();
$this->admin_login();
$this->add_lang(array('ucp', 'acp/groups'));
$this->enable_all_avatars();
$crawler = self::request('GET', $this->get_url() . '&g=5&sid=' . $this->sid);
$form = $crawler->selectButton($this->lang('SUBMIT'))->form();
$form['avatar_driver']->setValue($avatar_type);
$form[$form_name]->setValue($input);
$crawler = self::submit($form);
$this->assertContains($this->lang($expected), $crawler->text());
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
*
* @package testing
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @group functional
*/
class phpbb_functional_forum_style_test extends phpbb_functional_test_case
{
public function test_default_forum_style()
{
$crawler = self::request('GET', 'viewtopic.php?t=1&f=2');
$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1');
$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1&view=next');
$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
}
public function test_custom_forum_style()
{
$db = $this->get_db();
$this->add_style(2, 'test_style');
$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 2 WHERE forum_id = 2');
$crawler = self::request('GET', 'viewtopic.php?t=1&f=2');
$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1');
$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
$crawler = self::request('GET', 'viewtopic.php?t=1&view=next');
$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href'));
$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 0 WHERE forum_id = 2');
$this->delete_style(2, 'test_style');
}
}

View file

@ -15,9 +15,7 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case
{
$this->setup_engine(array('tpl_allow_php' => true));
$cache_file = $this->template->cachepath . 'includephp_relative.html.php';
$this->run_template('includephp_relative.html', array(), array(), array(), "Path is relative to board root.\ntesting included php", $cache_file);
$this->run_template('includephp_relative.html', array(), array(), array(), "Path is relative to board root.\ntesting included php");
$this->template->set_filenames(array('test' => 'includephp_relative.html'));
$this->assertEquals("Path is relative to board root.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");
@ -27,9 +25,7 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case
{
$this->setup_engine(array('tpl_allow_php' => true));
$cache_file = $this->template->cachepath . 'includephp_variables.html.php';
$this->run_template('includephp_variables.html', array('TEMPLATES' => 'templates'), array(), array(), "Path includes variables.\ntesting included php", $cache_file);
$this->run_template('includephp_variables.html', array('TEMPLATES' => 'templates'), array(), array(), "Path includes variables.\ntesting included php");
$this->template->set_filenames(array('test' => 'includephp_variables.html'));
$this->assertEquals("Path includes variables.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");
@ -37,11 +33,13 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case
public function test_includephp_absolute()
{
$path_to_php = dirname(__FILE__) . '/templates/_dummy_include.php.inc';
global $phpbb_root_path;
$path_to_php = str_replace('\\', '/', dirname(__FILE__)) . '/templates/_dummy_include.php.inc';
$this->assertTrue(phpbb_is_absolute($path_to_php));
$template_text = "Path is absolute.\n<!-- INCLUDEPHP $path_to_php -->";
$cache_dir = dirname($this->template->cachepath) . '/';
$cache_dir = $phpbb_root_path . 'cache/';
$fp = fopen($cache_dir . 'includephp_absolute.html', 'w');
fputs($fp, $template_text);
fclose($fp);
@ -49,9 +47,8 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case
$this->setup_engine(array('tpl_allow_php' => true));
$this->style->set_custom_style('tests', $cache_dir, array(), '');
$cache_file = $this->template->cachepath . 'includephp_absolute.html.php';
$this->run_template('includephp_absolute.html', array(), array(), array(), "Path is absolute.\ntesting included php", $cache_file);
$this->run_template('includephp_absolute.html', array(), array(), array(), "Path is absolute.\ntesting included php");
$this->template->set_filenames(array('test' => 'includephp_absolute.html'));
$this->assertEquals("Path is absolute.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");

View file

@ -1,87 +0,0 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/template_test_case.php';
class phpbb_template_invalid_constructs_test extends phpbb_template_template_test_case
{
public function template_data()
{
return array(
array(
'Unknown tag',
'invalid/unknown_tag.html',
array(),
array(),
array(),
'invalid/output/unknown_tag.html',
),
/*
* Produces a parse error which is fatal, therefore
* destroying the test suite.
array(
'ENDIF without IF',
'invalid/endif_without_if.html',
array(),
array(),
array(),
'invalid/output/endif_without_if.html',
),
*/
);
}
public function template_data_error()
{
return array(
array(
'Include a nonexistent file',
'invalid/include_nonexistent_file.html',
array(),
array(),
array(),
E_USER_ERROR,
'invalid/output/include_nonexistent_file.html',
),
);
}
/**
* @dataProvider template_data
*/
public function test_template($description, $file, $vars, $block_vars, $destroy, $expected)
{
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->assertFileNotExists($cache_file);
$expected = file_get_contents(dirname(__FILE__) . '/templates/' . $expected);
// apparently the template engine does not put
// the trailing newline into compiled templates
$expected = trim($expected);
$this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
}
/**
* @dataProvider template_data_error
*/
public function test_template_error($description, $file, $vars, $block_vars, $destroy, $error, $expected)
{
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->assertFileNotExists($cache_file);
$expected = file_get_contents(dirname(__FILE__) . '/templates/' . $expected);
// apparently the template engine does not put
// the trailing newline into compiled templates
$expected = trim($expected);
$this->setExpectedTriggerError($error, $expected);
$this->run_template($file, $vars, $block_vars, $destroy, '', $cache_file);
}
}

View file

@ -1,31 +0,0 @@
<?php
/**
*
* @package testing
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_template_renderer_eval_test extends phpbb_test_case
{
public function test_eval()
{
$compiled_code = '<a href="<?php echo \'Test\'; ?>">';
$valid_code = '<a href="Test">';
$context = new phpbb_template_context();
$template = new phpbb_template_renderer_eval($compiled_code, NULL);
ob_start();
try
{
$template->render($context, array());
}
catch (Exception $exception)
{
ob_end_clean();
throw $exception;
}
$output = ob_get_clean();
$this->assertEquals($valid_code, $output);
}
}

View file

@ -19,9 +19,7 @@ class phpbb_template_subdir_includephp_from_subdir_test extends phpbb_template_t
{
$this->setup_engine(array('tpl_allow_php' => true));
$cache_file = $this->template->cachepath . 'includephp_relative.html.php';
$this->run_template('includephp_relative.html', array(), array(), array(), "Path is relative to board root.\ntesting included php", $cache_file);
$this->run_template('includephp_relative.html', array(), array(), array(), "Path is relative to board root.\ntesting included php");
$this->template->set_filenames(array('test' => 'includephp_relative.html'));
$this->assertEquals("Path is relative to board root.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");

View file

@ -1,31 +0,0 @@
<?php
/**
*
* @package testing
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_template_template_compile_test extends phpbb_test_case
{
private $template_compile;
private $template_path;
protected function setUp()
{
$this->template_compile = new phpbb_template_compile(false, null, $this->style_resource_locator, '');
$this->template_path = dirname(__FILE__) . '/templates';
}
public function test_in_phpbb()
{
$output = $this->template_compile->compile_file($this->template_path . '/trivial.html');
$this->assertTrue(strlen($output) > 0);
$statements = explode(';', $output);
$first_statement = $statements[0];
$this->assertTrue(!!preg_match('#if.*defined.*IN_PHPBB.*exit#', $first_statement));
}
}

View file

@ -54,11 +54,9 @@ class phpbb_template_template_events_test extends phpbb_template_template_test_c
array(),
array(),
array(),
'Kappa test event in all
Omega test event in all
Zeta test event in all
Kappa test event in silver
Omega test event in silver',
'Kappa test event in silver
Omega test event in silver
Zeta test event in all',
),
array(
'Template event with inheritance - child',
@ -68,10 +66,9 @@ Omega test event in silver',
array(),
array(),
array(),
'Kappa test event in all
Omega test event in all
Zeta test event in all
Kappa test event in silver_inherit',
'Kappa test event in silver_inherit
Omega test event in silver
Zeta test event in all',
),
array(
'Definition in parent style',
@ -95,8 +92,7 @@ Kappa test event in silver_inherit',
$this->setup_engine_for_events($dataset, $style_names);
// Run test
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
$this->run_template($file, $vars, $block_vars, $destroy, $expected);
}
protected function setup_engine_for_events($dataset, $style_names, array $new_config = array())
@ -111,7 +107,7 @@ Kappa test event in silver_inherit',
$this->extension_manager = new phpbb_mock_filesystem_extension_manager(
dirname(__FILE__) . "/datasets/$dataset/"
);
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, new phpbb_template_context, $this->extension_manager);
$this->template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $user, new phpbb_template_context, $this->extension_manager);
$this->style_provider = new phpbb_style_path_provider();
$this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, $this->style_provider, $this->template);
$this->style->set_custom_style('silver', array($this->template_path), $style_names, '');

View file

@ -0,0 +1,28 @@
<?php
/**
*
* @package testing
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/template_test_case_with_tree.php';
class phpbb_template_template_includecss_test extends phpbb_template_template_test_case_with_tree
{
public function test_includecss_compilation()
{
// Reset the engine state
$this->setup_engine(array('assets_version' => 1));
// Prepare correct result
$scripts = array(
'<link href="' . $this->test_path . '/templates/child_only.css?assets_version=1" rel="stylesheet" type="text/css" media="screen, projection" />',
'<link href="' . $this->test_path . '/parent_templates/parent_only.css?assets_version=1" rel="stylesheet" type="text/css" media="screen, projection" />',
);
// Run test
$this->run_template('includecss.html', array(), array(), array(), implode('', $scripts));
}
}

View file

@ -11,23 +11,97 @@ require_once dirname(__FILE__) . '/template_test_case_with_tree.php';
class phpbb_template_template_includejs_test extends phpbb_template_template_test_case_with_tree
{
public function test_includejs_compilation()
public function template_data()
{
return array(
/*
array(
// vars
// expected
),
*/
array(
array('TEST' => 1),
'<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?assets_version=1"></script>',
),
array(
array('TEST' => 2),
'<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?assets_version=0&assets_version=1"></script>',
),
array(
array('TEST' => 3),
'<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?test=1&assets_version=0&assets_version=1"></script>',
),
array(
array('TEST' => 4),
'<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?test=1&amp;assets_version=0&assets_version=1"></script>',
),
array(
array('TEST' => 5),
'<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?test=1;assets_version=0&assets_version=1"></script>',
),
array(
array('TEST' => 6),
'<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?assets_version=1"></script>',
),
array(
array('TEST' => 7),
'<script type="text/javascript" src="' . $this->test_path . '/templates/child_only.js?assets_version=1"></script>',
),
array(
array('TEST' => 8),
'<script type="text/javascript" src="' . $this->test_path . '/templates/subdir/parent_only.js?assets_version=1"></script>',
),
array(
array('TEST' => 9),
'<script type="text/javascript" src="' . $this->test_path . '/templates/subdir/subsubdir/parent_only.js?assets_version=1"></script>',
),
array(
array('TEST' => 10),
'<script type="text/javascript" src="' . $this->test_path . '/templates/subdir/parent_only.js?assets_version=1"></script>',
),
array(
array('TEST' => 11),
'<script type="text/javascript" src="' . $this->test_path . '/templates/child_only.js?test1=1&amp;test2=2&assets_version=1#test3"></script>',
),
array(
array('TEST' => 12),
'<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?test1=1&amp;test2=2&assets_version=1#test3"></script>',
),
array(
array('TEST' => 13),
'<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?test1=1;test2=2&assets_version=1#test3"></script>',
),
array(
array('TEST' => 14),
'<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?test1=&quot;&assets_version=1#test3"></script>',
),
array(
array('TEST' => 15),
'<script type="text/javascript" src="http://phpbb.com/b.js?c=d#f"></script>',
),
array(
array('TEST' => 16),
'<script type="text/javascript" src="http://phpbb.com/b.js?c=d&assets_version=1#f"></script>',
),
array(
array('TEST' => 17),
'<script type="text/javascript" src="//phpbb.com/b.js"></script>',
),
);
}
/**
* @dataProvider template_data
*/
public function test_includejs_compilation($vars, $expected)
{
// Reset the engine state
$this->setup_engine(array('assets_version' => 1));
// Prepare correct result
$scripts = array(
'<script src="' . $this->test_path . '/templates/parent_and_child.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/parent_templates/parent_only.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/templates/child_only.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/templates/subdir/parent_only.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/templates/subdir/subsubdir/parent_only.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/templates/subdir/parent_only.js?assets_version=1"></script>',
);
$this->template->assign_vars($vars);
// Run test
$cache_file = $this->template->cachepath . 'includejs.html.php';
$this->run_template('includejs.html', array('PARENT' => 'parent_only.js', 'SUBDIR' => 'subdir', 'EXT' => 'js'), array(), array(), implode('', $scripts), $cache_file);
$this->run_template('includejs.html', array_merge(array('PARENT' => 'parent_only.js', 'SUBDIR' => 'subdir', 'EXT' => 'js'), $vars), array(), array(), $expected);
}
}

View file

@ -50,15 +50,6 @@ class phpbb_template_template_inheritance_test extends phpbb_template_template_t
*/
public function test_template($name, $file, array $vars, array $block_vars, array $destroy, $expected)
{
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->assertFileNotExists($cache_file);
$this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
// Reset the engine state
$this->setup_engine();
$this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
$this->run_template($file, $vars, $block_vars, $destroy, $expected);
}
}

Some files were not shown because too many files have changed in this diff Show more