diff options
Diffstat (limited to 'tests')
429 files changed, 14031 insertions, 1913 deletions
diff --git a/tests/RUNNING_TESTS.md b/tests/RUNNING_TESTS.md index afd7caa709..b082197166 100644 --- a/tests/RUNNING_TESTS.md +++ b/tests/RUNNING_TESTS.md @@ -120,8 +120,9 @@ directory (above phpBB):  Slow tests  -------------- -Certain tests, such as the UTF-8 normalizer or the DNS tests tend to be slow. -Thus these tests are in the `slow` group, which is excluded by default. If you +Certain tests, such as the DNS tests tend to be slow. +Thus these tests are in the `slow` group, which is excluded by default. You can +enable slow tests by copying the phpunit.xml.all file to phpunit.xml. If you  only want the slow tests, run:      $ phpBB/vendor/bin/phpunit --group slow diff --git a/tests/attachment/delete_test.php b/tests/attachment/delete_test.php new file mode 100644 index 0000000000..f1835dd37a --- /dev/null +++ b/tests/attachment/delete_test.php @@ -0,0 +1,127 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once(dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'); + +class phpbb_attachment_delete_test extends \phpbb_database_test_case +{ +	/** @var \phpbb\config\config */ +	protected $config; + +	/** @var \phpbb\db\driver\driver_interface */ +	protected $db; + +	/** @var \phpbb\filesystem\filesystem */ +	protected $filesystem; + +	/** @var \phpbb\attachment\resync */ +	protected $resync; + +	/** @var \phpbb\attachment\delete */ +	protected $attachment_delete; + +	protected $phpbb_root_path; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/resync.xml'); +	} + +	public function setUp() +	{ +		global $db, $phpbb_root_path; + +		parent::setUp(); + +		$this->config = new \phpbb\config\config(array()); +		$this->db = $this->new_dbal(); +		$db = $this->db; +		$this->resync = new \phpbb\attachment\resync($this->db); +		$this->filesystem = $this->getMock('\phpbb\filesystem\filesystem', array('remove', 'exists')); +		$this->filesystem->expects($this->any()) +			->method('remove') +			->willReturn(false); +		$this->filesystem->expects($this->any()) +			->method('exists') +			->willReturn(true); +		$this->phpbb_root_path = $phpbb_root_path; +		$this->dispatcher = new \phpbb_mock_event_dispatcher(); +		$this->attachment_delete = new \phpbb\attachment\delete($this->config, $this->db, $this->dispatcher, $this->filesystem, $this->resync, $phpbb_root_path); +	} + +	public function data_attachment_delete() +	{ +		return array( +			array('attach', '', false, false), +			array('meh', 5, false, 0), +			array('attach', array(5), false, 0), +			array('attach', array(1,2), false, 2), +			array('attach', array(1,2), true, 2), +			array('post', 5, false, 0), +			array('topic', 5, false, 0), +			array('topic', 1, true, 3), +			array('user', 1, false, 0), +		); +	} + +	/** +	 * @dataProvider data_attachment_delete +	 */ +	public function test_attachment_delete($mode, $ids, $resync, $expected) +	{ +		// We need to reset the attachment ID sequence to properly test this +		if ($this->db->get_sql_layer() === 'postgres') +		{ +			$sql = 'ALTER SEQUENCE phpbb_attachments_seq RESTART WITH 1'; +			$this->db->sql_query($sql); +		} + +		$this->assertSame($expected, $this->attachment_delete->delete($mode, $ids, $resync)); +	} + +	public function data_attachment_unlink() +	{ +		return array( +			array(true, true, true), +			array(true, false, false), +			array(true, true, false, true), +		); +	} + +	/** +	 * @dataProvider data_attachment_unlink +	 */ +	public function test_attachment_delete_success($remove_success, $exists_success, $expected, $throw_exception = false) +	{ +		$this->filesystem = $this->getMock('\phpbb\filesystem\filesystem', array('remove', 'exists')); +		if ($throw_exception) +		{ +			$this->filesystem->expects($this->any()) +				->method('remove') +				->willThrowException(new \phpbb\filesystem\exception\filesystem_exception);; +		} +		else +		{ +			$this->filesystem->expects($this->any()) +				->method('remove') +				->willReturn($remove_success); +		} + +		$this->filesystem->expects($this->any()) +			->method('exists') +			->willReturn($exists_success); + +		$this->attachment_delete = new \phpbb\attachment\delete($this->config, $this->db, $this->dispatcher, $this->filesystem, $this->resync, $this->phpbb_root_path); +		$this->assertSame($expected, $this->attachment_delete->unlink_attachment('foobar')); +	} +} diff --git a/tests/attachment/fixtures/resync.xml b/tests/attachment/fixtures/resync.xml new file mode 100644 index 0000000000..6e2cc62f68 --- /dev/null +++ b/tests/attachment/fixtures/resync.xml @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +    <table name="phpbb_attachments"> +        <column>post_msg_id</column> +        <column>topic_id</column> +        <column>in_message</column> +        <column>is_orphan</column> +        <column>attach_comment</column> +        <column>physical_filename</column> +        <column>thumbnail</column> +        <row> +            <value>1</value> +            <value>1</value> +            <value>0</value> +            <value>0</value> +            <value>foo</value> +            <value>foo</value> +            <value>0</value> +        </row> +        <row> +            <value>1</value> +            <value>1</value> +            <value>1</value> +            <value>0</value> +            <value>foo2</value> +            <value>foo2</value> +            <value>0</value> +        </row> +        <row> +            <value>1</value> +            <value>1</value> +            <value>1</value> +            <value>0</value> +            <value>foo2</value> +            <value>foo2</value> +            <value>1</value> +        </row> +    </table> +    <table name="phpbb_extensions"> +        <column>extension</column> +        <column>group_id</column> +        <row> +            <value>jpg</value> +            <value>1</value> +        </row> +        <row> +            <value>png</value> +            <value>1</value> +        </row> +    </table> +    <table name="phpbb_extension_groups"> +        <column>cat_id</column> +        <column>group_id</column> +        <column>download_mode</column> +        <column>upload_icon</column> +        <column>max_filesize</column> +        <column>allow_group</column> +        <column>allow_in_pm</column> +        <column>allowed_forums</column> +        <column>group_name</column> +        <row> +            <value>1</value> +            <value>1</value> +            <value>1</value> +            <value> </value> +            <value>1000</value> +            <value>1</value> +            <value>1</value> +            <value>a:1:{i:0;i:1;}</value> +            <value>Images</value> +        </row> +    </table> +    <table name="phpbb_posts"> +        <column>post_id</column> +        <column>post_text</column> +        <column>poster_id</column> +        <column>post_attachment</column> +        <row> +            <value>1</value> +            <value>foo</value> +            <value>1</value> +            <value>1</value> +        </row> +        <row> +            <value>2</value> +            <value>foo</value> +            <value>1</value> +            <value>1</value> +        </row> +    </table> +    <table name="phpbb_privmsgs"> +        <column>msg_id</column> +        <column>message_text</column> +        <column>message_attachment</column> +        <column>to_address</column> +        <column>bcc_address</column> +        <row> +            <value>1</value> +            <value>foo</value> +            <value>1</value> +            <value>2</value> +            <value>2</value> +        </row> +        <row> +            <value>2</value> +            <value>foo</value> +            <value>1</value> +            <value>2</value> +            <value>2</value> +        </row> +    </table> +    <table name="phpbb_topics"> +        <column>topic_id</column> +        <column>forum_id</column> +        <column>topic_title</column> +        <column>topic_attachment</column> +        <row> +            <value>1</value> +            <value>1</value> +            <value>foo</value> +            <value>1</value> +        </row> +        <row> +            <value>2</value> +            <value>1</value> +            <value>bar</value> +            <value>1</value> +        </row> +    </table> +</dataset> diff --git a/tests/attachment/manager_test.php b/tests/attachment/manager_test.php new file mode 100644 index 0000000000..47d7f38b1d --- /dev/null +++ b/tests/attachment/manager_test.php @@ -0,0 +1,131 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_attachment_manager_test extends \phpbb_test_case +{ +	protected $delete; +	protected $resync; +	protected $upload; + +	public function setUp() +	{ +		$this->delete = $this->getMockBuilder('\phpbb\attachment\delete') +			->disableOriginalConstructor() +			->setMethods(['delete', 'unlink_attachment']) +			->getMock(); +		$this->resync = $this->getMockBuilder('\phpbb\attachment\resync') +			->disableOriginalConstructor() +			->setMethods(['resync']) +			->getMock(); +		$this->upload = $this->getMockBuilder('\phpbb\attachment\upload') +			->disableOriginalConstructor() +			->setMethods(['upload']) +			->getMock(); +	} + +	protected function get_manager() +	{ +		return new \phpbb\attachment\manager($this->delete, $this->resync, $this->upload); +	} + +	public function data_manager() +	{ +		return array( +			array( +				'delete', +				'unlink_attachment', +				'unlink', +				['foo'], +				['foo', 'file', false], +				true, +				true, +			), +			array( +				'delete', +				'unlink_attachment', +				'unlink', +				['foo', 'bar'], +				['foo', 'bar', false], +				true, +				true, +			), +			array( +				'delete', +				'unlink_attachment', +				'unlink', +				['foo', 'bar', true], +				['foo', 'bar', true], +				true, +				true, +			), +			array( +				'delete', +				'delete', +				'delete', +				['foo', [1, 2, 3]], +				['foo', [1, 2, 3], true], +				5, +				5, +			), +			array( +				'delete', +				'delete', +				'delete', +				['foo', [1, 2, 3], false], +				['foo', [1, 2, 3], false], +				2, +				2, +			), +			array( +				'resync', +				'resync', +				'resync', +				['foo', [1, 2, 3]], +				['foo', [1, 2, 3]], +				true, +				null, +			), +			array( +				'upload', +				'upload', +				'upload', +				['foo', 1], +				['foo', 1, false, '', false, []], +				true, +				true, +			), +			array( +				'upload', +				'upload', +				'upload', +				['foo', 1, true, 'bar', true, ['filename' => 'foobar']], +				['foo', 1, true, 'bar', true, ['filename' => 'foobar']], +				true, +				true, +			), +		); +	} + +	/** +	 * @dataProvider data_manager +	 */ +	public function test_manager($class, $method_class, $method_manager, $input_manager, $input_method, $return, $output) +	{ +		$mock = call_user_func_array([$this->{$class}, 'expects'], [$this->atLeastOnce()]); +		$mock = $mock->method($method_class); +		$mock = call_user_func_array([$mock, 'with'], $input_method); +		$mock->willReturn($return); +		$manager = $this->get_manager(); +		$this->assertSame($output, call_user_func_array([$manager, $method_manager], $input_manager)); +	} +} diff --git a/tests/attachment/resync_test.php b/tests/attachment/resync_test.php new file mode 100644 index 0000000000..f882af9ae5 --- /dev/null +++ b/tests/attachment/resync_test.php @@ -0,0 +1,74 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_attachment_resync_test extends \phpbb_database_test_case +{ +	/** @var \phpbb\db\driver\driver_interface */ +	protected $db; + +	/** @var \phpbb\attachment\resync */ +	protected $resync; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/resync.xml'); +	} + +	public function setUp() +	{ +		parent::setUp(); + +		$this->db = $this->new_dbal(); +		$this->resync = new \phpbb\attachment\resync($this->db); +	} + +	public function data_resync() +	{ +		return array( +			array('', array(1), 'post_id', POSTS_TABLE, array('post_attachment' => '1'), array('post_attachment' => '1')), +			array('post', array(1), 'post_id', POSTS_TABLE, array('post_attachment' => '1'), array('post_attachment' => '1')), +			array('post', array(2), 'post_id', POSTS_TABLE, array('post_attachment' => '1'), array('post_attachment' => '0')), +			array('topic', array(1), 'topic_id', TOPICS_TABLE, array('topic_attachment' => '1'), array('topic_attachment' => '1')), +			array('topic', array(2), 'topic_id', TOPICS_TABLE, array('topic_attachment' => '1'), array('topic_attachment' => '0')), +			array('message', array(1), 'msg_id', PRIVMSGS_TABLE, array('message_attachment' => '1'), array('message_attachment' => '1')), +			array('message', array(2), 'msg_id', PRIVMSGS_TABLE, array('message_attachment' => '1'), array('message_attachment' => '0')), +		); +	} + +	/** +	 * @dataProvider data_resync +	 */ +	public function test_resync($type, $ids, $sql_id, $exist_table, $exist_data, $resync_data) +	{ +		$sql_prefix = ($type) ?: 'post'; +		$sql = 'SELECT ' . $sql_prefix . '_attachment +			FROM ' . $exist_table . ' +			WHERE ' . $sql_id . ' = ' . $ids[0]; +		$result = $this->db->sql_query($sql); +		$data = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		$this->assertEquals($exist_data, $data); + +		$this->resync->resync($type, $ids); + +		$sql = 'SELECT ' . $sql_prefix . '_attachment +			FROM ' . $exist_table . ' +			WHERE ' . $sql_id . ' = ' . $ids[0]; +		$result = $this->db->sql_query($sql); +		$data = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		$this->assertEquals($resync_data, $data); +	} +} diff --git a/tests/attachment/upload_test.php b/tests/attachment/upload_test.php new file mode 100644 index 0000000000..235ecd082a --- /dev/null +++ b/tests/attachment/upload_test.php @@ -0,0 +1,429 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once(dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'); + +class phpbb_attachment_upload_test extends \phpbb_database_test_case +{ +	/** @var \phpbb\auth\auth */ +	protected $auth; + +	/** @var \phpbb\cache\service */ +	protected $cache; + +	/** @var \phpbb\config\config */ +	protected $config; + +	/** @var \phpbb\files\upload */ +	protected $files_upload; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\mimetype\guesser */ +	protected $mimetype_guesser; + +	/** @var \phpbb\event\dispatcher */ +	protected $phpbb_dispatcher; + +	/** @var \phpbb\plupload\plupload */ +	protected $plupload; + +	/** @var \phpbb\user */ +	protected $user; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	/** @var \phpbb\db\driver\driver_interface */ +	protected $db; + +	/** @var \phpbb\attachment\upload */ +	protected $upload; + +	private $filesystem; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/resync.xml'); +	} + +	public function setUp() +	{ +		global $config, $phpbb_root_path, $phpEx; + +		parent::setUp(); + +		$this->auth = new \phpbb\auth\auth(); +		$this->config = new \phpbb\config\config(array( +			'upload_path'	=> '', +			'img_create_thumbnail'	=> true, +		)); +		$config = $this->config; +		$this->db = $this->new_dbal(); +		$this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), $this->config, $this->db, $phpbb_root_path, $phpEx); +		$this->request = $this->getMock('\phpbb\request\request'); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; +		$guessers = array( +			new \Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser(), +			new \Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser(), +			new \phpbb\mimetype\content_guesser(), +			new \phpbb\mimetype\extension_guesser(), +		); +		$guessers[2]->set_priority(-2); +		$guessers[3]->set_priority(-2); +		$this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers); +		$this->plupload = new \phpbb\plupload\plupload($phpbb_root_path, $this->config, $this->request, new \phpbb\user($this->language, '\phpbb\datetime'), $this->php_ini, $this->mimetype_guesser); +		$factory_mock = $this->getMockBuilder('\phpbb\files\factory') +			->disableOriginalConstructor() +			->getMock(); +		$factory_mock->expects($this->any()) +			->method('get') +			->willReturn(new \phpbb\files\filespec( +				$this->filesystem, +				$this->language, +				$this->php_ini, +				new \FastImageSize\FastImageSize(), +				$this->phpbb_root_path, +				$this->mimetype_guesser +			)); + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->container->set('files.types.form', new \phpbb\files\types\form( +			$factory_mock, +			$this->language, +			$this->php_ini, +			$this->plupload, +			$this->request +		)); +		$this->container->set('files.types.local', new \phpbb\files\types\local( +			$factory_mock, +			$this->language, +			$this->php_ini, +			$this->request +		)); +		$this->factory = new \phpbb\files\factory($this->container); +		$this->files_upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$this->phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		$this->user = new \phpbb\user($this->language, '\phpbb\datetime'); + + +		$this->upload = new \phpbb\attachment\upload( +			$this->auth, +			$this->cache, +			$this->config, +			$this->files_upload, +			$this->language, +			$this->mimetype_guesser, +			$this->phpbb_dispatcher, +			$this->plupload, +			$this->user, +			$this->phpbb_root_path +		); +	} + +	public function data_upload() +	{ +		return array( +			array('foobar', 1, false, +				array(), +				array( +					'error' => array( +						'Upload initiated but no valid file upload form found.', +					), +					'post_attach'	=> false, +				) +			), +			array('foobar', 1, true, +				array( +					'realname'		=> 'foobar.jpg', +					'type'			=> 'jpg', +					'size'			=> 100, +				), +				array( +					'error' => array( +						'NOT_UPLOADED', +						'The image file you tried to attach is invalid.', +					), +					'post_attach'	=> false, +					'thumbnail'		=> 1, +				) +			), +			array('foobar', 1, true, +				array(), +				array( +					'error' => array( +						'NOT_UPLOADED', +					), +					'post_attach'	=> false, +					'thumbnail'		=> 0, +				) +			), +		); +	} + +	/** +	 * @dataProvider data_upload +	 */ +	public function test_upload($form_name, $forum_id, $local, $filedata, $expected) +	{ +		$filedata = $this->upload->upload($form_name, $forum_id, $local, '', false, $filedata); + +		$this->assertSame($expected, $filedata); +	} + +	public function test_init_error() +	{ +		$filespec = $this->getMockBuilder('\phpbb\files\filespec') +			->disableOriginalConstructor() +			->getMock(); +		$filespec->expects($this->any()) +			->method('init_error') +			->willReturn(true); +		$filespec->expects($this->any()) +			->method('set_upload_namespace') +			->willReturnSelf(); +		$filespec->expects($this->any()) +			->method('set_upload_ary') +			->willReturnSelf(); +		$this->container->set('files.filespec', $filespec); +		$factory_mock = $this->getMockBuilder('\phpbb\files\factory') +			->disableOriginalConstructor() +			->getMock(); +		$factory_mock->expects($this->any()) +			->method('get') +			->willReturn($filespec); +		$this->container->set('files.types.local', new \phpbb\files\types\local( +			$factory_mock, +			$this->language, +			$this->php_ini, +			$this->request +		)); + +		$this->upload = new \phpbb\attachment\upload( +			$this->auth, +			$this->cache, +			$this->config, +			$this->files_upload, +			$this->language, +			$this->mimetype_guesser, +			$this->phpbb_dispatcher, +			$this->plupload, +			$this->user, +			$this->phpbb_root_path +		); + +		$filedata = $this->upload->upload('foobar', 1, true); + +		$this->assertSame(array( +			'error'		=> array(), +			'post_attach'	=> false, +		), $filedata); +	} + +	public function data_image_upload() +	{ +		return array( +			array(false, false, array(), +				array( +					'error'			=> array('The image file you tried to attach is invalid.'), +					'post_attach'	=> false, +					'thumbnail'		=> 1, +				) +			), +			array(false, true, array(), +				array( +					'error'			=> array('The image file you tried to attach is invalid.'), +					'post_attach'	=> false, +					'thumbnail'		=> 1, +				) +			), +			array(true, false, array(), +				array( +					'error'			=> array(), +					'post_attach'	=> true, +					// thumbnail gets reset to 0 as creation was not possible +					'thumbnail'		=> 0, +					'filesize'		=> 100, +					'mimetype'		=> 'jpg', +					'extension'		=> 'jpg', +					'real_filename'	=> 'foobar.jpg', +				) +			), +			array(true, false, +				array( +					'check_attachment_content'	=> true, +					'mime_triggers'	=> '', +				), +				array( +					'error'			=> array(), +					'post_attach'	=> true, +					// thumbnail gets reset to 0 as creation was not possible +					'thumbnail'		=> 0, +					'filesize'		=> 100, +					'mimetype'		=> 'jpg', +					'extension'		=> 'jpg', +					'real_filename'	=> 'foobar.jpg', +				) +			), +			array(true, false, +				array( +					'attachment_quota'	=> 150, +				), +				array( +					'error'			=> array(), +					'post_attach'	=> true, +					// thumbnail gets reset to 0 as creation was not possible +					'thumbnail'		=> 0, +					'filesize'		=> 100, +					'mimetype'		=> 'jpg', +					'extension'		=> 'jpg', +					'real_filename'	=> 'foobar.jpg', +				) +			), +			array(true, false, +				array( +					'attachment_quota'	=> 50, +				), +				array( +					'error'			=> array( +						'ATTACH_QUOTA_REACHED', +					), +					'post_attach'	=> false, +					'thumbnail'		=> 1, +					'filesize'		=> 100, +					'mimetype'		=> 'jpg', +					'extension'		=> 'jpg', +					'real_filename'	=> 'foobar.jpg', +				) +			), +		); +	} + +	/** +	 * @dataProvider data_image_upload +	 */ +	public function test_image_upload($is_image, $plupload_active, $config_data, $expected) +	{ +		$filespec = $this->getMock('\phpbb\files\filespec', +			array( +				'init_error', +				'is_image', +				'move_file', +				'is_uploaded', +			), +			array( +				$this->filesystem, +				$this->language, +				$this->php_ini, +				new \FastImageSize\FastImageSize(), +				$this->phpbb_root_path, +				$this->mimetype_guesser, +				$this->plupload +			)); +		foreach ($config_data as $key => $value) +		{ +			$this->config[$key] = $value; +		} +		$filespec->set_upload_namespace($this->files_upload); +		$filespec->expects($this->any()) +			->method('init_error') +			->willReturn(false); +		$filespec->expects($this->any()) +			->method('is_image') +			->willReturn($is_image); +		$filespec->expects($this->any()) +			->method('is_uploaded') +			->willReturn(true); +		$filespec->expects($this->any()) +			->method('move_file') +			->willReturn(false); +		$this->container->set('files.filespec', $filespec); +		$factory_mock = $this->getMockBuilder('\phpbb\files\factory') +			->disableOriginalConstructor() +			->getMock(); +		$factory_mock->expects($this->any()) +			->method('get') +			->willReturn($filespec); +		$this->container->set('files.types.local', new \phpbb\files\types\local( +			$factory_mock, +			$this->language, +			$this->php_ini, +			$this->request +		)); + +		$plupload = $this->getMockBuilder('\phpbb\plupload\plupload') +			->disableOriginalConstructor() +			->getMock(); +		$plupload->expects($this->any()) +			->method('is_active') +			->willReturn($plupload_active); +		if ($plupload_active) +		{ +			$plupload->expects($this->once()) +				->method('emit_error') +				->with(104, 'ATTACHED_IMAGE_NOT_IMAGE') +				->willReturn(false); +		} +		$this->upload = new \phpbb\attachment\upload( +			$this->auth, +			$this->cache, +			$this->config, +			$this->files_upload, +			$this->language, +			$this->mimetype_guesser, +			$this->phpbb_dispatcher, +			$plupload, +			$this->user, +			$this->phpbb_root_path +		); + +		$filedata = $this->upload->upload('foobar', 1, true, '', false, array( +			'realname'		=> 'foobar.jpg', +			'type'			=> 'jpg', +			'size'			=> 100, +		)); + +		foreach ($expected as $key => $entry) +		{ +			$this->assertEquals($entry, $filedata[$key]); +		} + +		// Reset config data +		foreach ($config_data as $key => $value) +		{ +			$this->config->delete($key); +		} +	} +} diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index 68ad7b2c19..7d77d763fb 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_auth_provider_apache_test extends phpbb_database_test_case  {  	protected $provider; @@ -28,8 +25,10 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case  		$db = $this->new_dbal();  		$config = new \phpbb\config\config(array()); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader);  		$this->request = $this->getMock('\phpbb\request\request'); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		$this->user = new \phpbb\user($lang, '\phpbb\datetime');  		$driver_helper = new \phpbb\passwords\driver\helper($config);  		$passwords_drivers = array(  			'passwords.driver.bcrypt_2y'	=> new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index 09ca0816bf..6ff77da564 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_auth_provider_db_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -38,8 +35,10 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case  			'ip_login_limit_use_forwarded' 	=> 0,  			'max_login_attempts' 			=> 0,  			)); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader);  		$request = $this->getMock('\phpbb\request\request'); -		$user = new \phpbb\user('\phpbb\datetime'); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$driver_helper = new \phpbb\passwords\driver\helper($config);  		$passwords_drivers = array(  			'passwords.driver.bcrypt_2y'	=> new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), diff --git a/tests/auth/provider_oauth_token_storage_test.php b/tests/auth/provider_oauth_token_storage_test.php index 71b49ff439..ae5de6aa7e 100644 --- a/tests/auth/provider_oauth_token_storage_test.php +++ b/tests/auth/provider_oauth_token_storage_test.php @@ -22,6 +22,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c  	protected $session_id;  	protected $token_storage;  	protected $token_storage_table; +	protected $state_table;  	protected $user;  	protected function setup() @@ -31,9 +32,12 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c  		global $phpbb_root_path, $phpEx;  		$this->db = $this->new_dbal(); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$this->user = new \phpbb\user($lang, '\phpbb\datetime');  		$this->service_name = 'auth.provider.oauth.service.testing';  		$this->token_storage_table = 'phpbb_oauth_tokens'; +		$this->state_table = 'phpbb_oauth_states';  		// Give the user a session_id that we will remember  		$this->session_id = '12345'; @@ -42,7 +46,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c  		// Set the user id to anonymous  		$this->user->data['user_id'] = ANONYMOUS; -		$this->token_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table); +		$this->token_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);  	}  	public function getDataSet() @@ -96,7 +100,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c  		$expected_token = new StdOAuth2Token('access', 'refresh', StdOAuth2Token::EOL_NEVER_EXPIRES);  		// Store a token in the database -		$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table); +		$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->token_storage_table, $this->state_table);  		$temp_storage->storeAccessToken($this->service_name, $expected_token);  		unset($temp_storage); @@ -127,7 +131,7 @@ class phpbb_auth_provider_oauth_token_storage_test extends phpbb_database_test_c  		$expected_token = new StdOAuth2Token('access', 'refresh', StdOAuth2Token::EOL_NEVER_EXPIRES);  		// Store a token in the database -		$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user,  $this->token_storage_table); +		$temp_storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user,  $this->token_storage_table, $this->state_table);  		$temp_storage->storeAccessToken($this->service_name, $expected_token);  		unset($temp_storage); diff --git a/tests/avatar/driver/barfoo.php b/tests/avatar/driver/barfoo.php index 0bf30b8a91..067bb3ef97 100644 --- a/tests/avatar/driver/barfoo.php +++ b/tests/avatar/driver/barfoo.php @@ -1,26 +1,26 @@ -<?php
 -
 -namespace phpbb\avatar\driver;
 -
 -class barfoo extends \phpbb\avatar\driver\driver
 -{
 -	public function get_data($row)
 -	{
 -		return array();
 -	}
 -
 -	public function prepare_form($request, $template, $user, $row, &$error)
 -	{
 -		return false;
 -	}
 -
 -	public function process_form($request, $template, $user, $row, &$error)
 -	{
 -		return false;
 -	}
 -
 -	public function get_template_name()
 -	{
 -		return 'barfoo.html';
 -	}
 -}
 +<?php + +namespace phpbb\avatar\driver; + +class barfoo extends \phpbb\avatar\driver\driver +{ +	public function get_data($row) +	{ +		return array(); +	} + +	public function prepare_form($request, $template, $user, $row, &$error) +	{ +		return false; +	} + +	public function process_form($request, $template, $user, $row, &$error) +	{ +		return false; +	} + +	public function get_template_name() +	{ +		return 'barfoo.html'; +	} +} diff --git a/tests/avatar/driver/foobar.php b/tests/avatar/driver/foobar.php index aabdaf5ac4..16d50ccad4 100644 --- a/tests/avatar/driver/foobar.php +++ b/tests/avatar/driver/foobar.php @@ -1,26 +1,26 @@ -<?php
 -
 -namespace phpbb\avatar\driver;
 -
 -class foobar extends \phpbb\avatar\driver\driver
 -{
 -	public function get_data($row)
 -	{
 -		return array();
 -	}
 -
 -	public function prepare_form($request, $template, $user, $row, &$error)
 -	{
 -		return false;
 -	}
 -
 -	public function process_form($request, $template, $user, $row, &$error)
 -	{
 -		return false;
 -	}
 -
 -	public function get_template_name()
 -	{
 -		return 'foobar.html';
 -	}
 -}
 +<?php + +namespace phpbb\avatar\driver; + +class foobar extends \phpbb\avatar\driver\driver +{ +	public function get_data($row) +	{ +		return array(); +	} + +	public function prepare_form($request, $template, $user, $row, &$error) +	{ +		return false; +	} + +	public function process_form($request, $template, $user, $row, &$error) +	{ +		return false; +	} + +	public function get_template_name() +	{ +		return 'foobar.html'; +	} +} diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php index 344eef38ff..924f1319a2 100644 --- a/tests/avatar/manager_test.php +++ b/tests/avatar/manager_test.php @@ -35,6 +35,8 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case  			->method('get')  			->will($this->returnArgument(0)); +		$filesystem = new \phpbb\filesystem\filesystem(); +  		// Prepare dependencies for avatar manager and driver  		$this->config = new \phpbb\config\config(array());  		$cache = $this->getMock('\phpbb\cache\driver\driver_interface'); @@ -42,7 +44,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			$filesystem,  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			$phpEx @@ -55,11 +57,12 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case  			new \phpbb\mimetype\content_guesser,  		);  		$guesser = new \phpbb\mimetype\guesser($guessers); +		$imagesize = new \FastImageSize\FastImageSize();  		$dispatcher = new phpbb_mock_event_dispatcher();  		// $this->avatar_foobar will be needed later on -		$this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache)); +		$this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache));  		$this->avatar_foobar->expects($this->any())  			->method('get_name')  			->will($this->returnValue('avatar.driver.foobar')); @@ -73,15 +76,17 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case  			->will($this->returnValue('barfoo'));  		$avatar_drivers = array($this->avatar_foobar, $this->avatar_barfoo); +		$files_factory = new \phpbb\files\factory($phpbb_container); +  		foreach ($this->avatar_drivers() as $driver)  		{  			if ($driver !== 'upload')  			{ -				$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache)); +				$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache));  			}  			else  			{ -				$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $guesser, $dispatcher, $cache)); +				$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $filesystem, $path_helper, $dispatcher, $files_factory, $cache));  			}  			$cur_avatar->expects($this->any())  				->method('get_name') @@ -96,7 +101,9 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case  		// Set up avatar manager  		$this->manager = new \phpbb\avatar\manager($this->config, $avatar_drivers, $phpbb_container);  		$this->db = $this->new_dbal(); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$this->user = new \phpbb\user($lang, '\phpbb\datetime');  	}  	protected function avatar_drivers() @@ -279,7 +286,12 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case  	public function test_localize_errors()  	{ -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime') +		);  		$lang_array = array(  			array('FOOBAR_OFF', 'foobar_off'),  			array('FOOBAR_EXPLAIN', 'FOOBAR_EXPLAIN %s'), diff --git a/tests/bbcode/parser_test.php b/tests/bbcode/parser_test.php index 14736627f3..5677e49636 100644 --- a/tests/bbcode/parser_test.php +++ b/tests/bbcode/parser_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/bbcode.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/message_parser.php'; diff --git a/tests/bbcode/url_bbcode_test.php b/tests/bbcode/url_bbcode_test.php index 83176abe4c..3f8ad6022f 100644 --- a/tests/bbcode/url_bbcode_test.php +++ b/tests/bbcode/url_bbcode_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/bbcode.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/message_parser.php'; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 0e81f4372a..18977bac88 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,14 +12,21 @@  */  define('IN_PHPBB', true); +define('PHPBB_ENVIRONMENT', 'test'); +  $phpbb_root_path = 'phpBB/';  $phpEx = 'php'; + +global $table_prefix;  require_once $phpbb_root_path . 'includes/startup.php';  $table_prefix = 'phpbb_';  require_once $phpbb_root_path . 'includes/constants.php';  require_once $phpbb_root_path . 'phpbb/class_loader.' . $phpEx; -require_once($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); +require_once $phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx; +require_once $phpbb_root_path . 'includes/functions.' . $phpEx; +require_once $phpbb_root_path . 'includes/functions_content.' . $phpEx; +require_once $phpbb_root_path . 'includes/functions_compatibility.' . $phpEx;  $phpbb_class_loader_mock = new \phpbb\class_loader('phpbb_mock_', $phpbb_root_path . '../tests/mock/', "php");  $phpbb_class_loader_mock->register(); diff --git a/tests/cache/apc_driver_test.php b/tests/cache/apc_driver_test.php index 10130b465b..706f274448 100644 --- a/tests/cache/apc_driver_test.php +++ b/tests/cache/apc_driver_test.php @@ -34,14 +34,14 @@ class phpbb_cache_apc_driver_test extends phpbb_cache_common_test_case  			self::markTestSkipped('APC extension is not loaded');  		} -		$php_ini = new \phpbb\php\ini; +		$php_ini = new \bantu\IniGetWrapper\IniGetWrapper; -		if (!$php_ini->get_bool('apc.enabled')) +		if (!$php_ini->getBool('apc.enabled'))  		{  			self::markTestSkipped('APC is not enabled. Make sure apc.enabled=1 in php.ini');  		} -		if (PHP_SAPI == 'cli' && !$php_ini->get_bool('apc.enable_cli')) +		if (PHP_SAPI == 'cli' && !$php_ini->getBool('apc.enable_cli'))  		{  			self::markTestSkipped('APC is not enabled for CLI. Set apc.enable_cli=1 in php.ini');  		} diff --git a/tests/cache/null_driver_test.php b/tests/cache/dummy_driver_test.php index b9f96732f5..6cb6b73729 100644 --- a/tests/cache/null_driver_test.php +++ b/tests/cache/dummy_driver_test.php @@ -11,7 +11,7 @@  *  */ -class phpbb_cache_null_driver_test extends phpbb_database_test_case +class phpbb_cache_dummy_driver_test extends phpbb_database_test_case  {  	protected $driver; @@ -24,7 +24,7 @@ class phpbb_cache_null_driver_test extends phpbb_database_test_case  	{  		parent::setUp(); -		$this->driver = new \phpbb\cache\driver\null; +		$this->driver = new \phpbb\cache\driver\dummy;  	}  	public function test_get_put() diff --git a/tests/captcha/qa_test.php b/tests/captcha/qa_test.php index 1f2f9f3070..7ec4be69f5 100644 --- a/tests/captcha/qa_test.php +++ b/tests/captcha/qa_test.php @@ -11,8 +11,6 @@   *   */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_captcha_qa_test extends \phpbb_database_test_case  {  	protected $request; @@ -27,14 +25,16 @@ class phpbb_captcha_qa_test extends \phpbb_database_test_case  	public function setUp()  	{ -		global $db; +		global $db, $request, $phpbb_container;  		$db = $this->new_dbal();  		parent::setUp(); -		$this->request = new \phpbb_mock_request(); -		request_var(false, false, false, false, $this->request); +		$request = new \phpbb_mock_request(); +		$phpbb_container = new \phpbb_mock_container_builder(); +		$factory = new \phpbb\db\tools\factory(); +		$phpbb_container->set('dbal.tools', $factory->get($db));  		$this->qa = new \phpbb\captcha\plugins\qa('phpbb_captcha_questions', 'phpbb_captcha_answers', 'phpbb_qa_confirm');  	} @@ -87,7 +87,8 @@ class phpbb_captcha_qa_test extends \phpbb_database_test_case  	 */  	public function test_acp_get_question_input($value, $expected)  	{ -		$this->request->overwrite('answers', $value); +		global $request; +		$request->overwrite('answers', $value);  		$this->assertEquals($expected, $this->qa->acp_get_question_input());  	} diff --git a/tests/composer.json b/tests/composer.json deleted file mode 100644 index 057e0115a5..0000000000 --- a/tests/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ -	"require-dev": { -		"facebook/webdriver": "~1.1" -	} -} diff --git a/tests/composer.lock b/tests/composer.lock deleted file mode 100644 index f172de4669..0000000000 --- a/tests/composer.lock +++ /dev/null @@ -1,63 +0,0 @@ -{ -    "_readme": [ -        "This file locks the dependencies of your project to a known state", -        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", -        "This file is @generated automatically" -    ], -    "hash": "25ad22c35c19f2b0a2331640fb6b5577", -    "content-hash": "617c33144bd2877c3c9a78f167a871b6", -    "packages": [], -    "packages-dev": [ -        { -            "name": "facebook/webdriver", -            "version": "1.1.2", -            "source": { -                "type": "git", -                "url": "https://github.com/facebook/php-webdriver.git", -                "reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986" -            }, -            "dist": { -                "type": "zip", -                "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/0b889d7de7461439f8a3bbcca46e0f696cb27986", -                "reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986", -                "shasum": "" -            }, -            "require": { -                "ext-curl": "*", -                "php": ">=5.3.19" -            }, -            "require-dev": { -                "phpunit/phpunit": "4.6.*" -            }, -            "suggest": { -                "phpdocumentor/phpdocumentor": "2.*" -            }, -            "type": "library", -            "autoload": { -                "psr-4": { -                    "Facebook\\WebDriver\\": "lib/" -                } -            }, -            "notification-url": "https://packagist.org/downloads/", -            "license": [ -                "Apache-2.0" -            ], -            "description": "A PHP client for WebDriver", -            "homepage": "https://github.com/facebook/php-webdriver", -            "keywords": [ -                "facebook", -                "php", -                "selenium", -                "webdriver" -            ], -            "time": "2016-06-04 00:02:34" -        } -    ], -    "aliases": [], -    "minimum-stability": "stable", -    "stability-flags": [], -    "prefer-stable": false, -    "prefer-lowest": false, -    "platform": [], -    "platform-dev": [] -} diff --git a/tests/compress/compress_test.php b/tests/compress/compress_test.php index 56c406b206..c071a049a8 100644 --- a/tests/compress/compress_test.php +++ b/tests/compress/compress_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compress.php'; diff --git a/tests/console/cache/purge_test.php b/tests/console/cache/purge_test.php index 96988c1028..6c92660580 100644 --- a/tests/console/cache/purge_test.php +++ b/tests/console/cache/purge_test.php @@ -32,6 +32,8 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case  	protected function setUp()  	{ +		global $phpbb_root_path, $phpEx; +  		if (file_exists($this->cache_dir))  		{  			// cache directory possibly left after aborted @@ -45,7 +47,10 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case  		$this->db = $this->getMock('\phpbb\db\driver\driver_interface');  		$this->config = new \phpbb\config\config(array('assets_version' => 1)); -		$this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$this->user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime') +		);  	}  	public function test_purge() @@ -86,7 +91,7 @@ class phpbb_console_command_cache_purge_test extends phpbb_test_case  	public function get_command_tester()  	{  		$application = new Application(); -		$application->add(new purge($this->user, $this->cache, $this->db, $this->getMock('\phpbb\auth\auth'), new \phpbb\log\null(), $this->config)); +		$application->add(new purge($this->user, $this->cache, $this->db, $this->getMock('\phpbb\auth\auth'), new \phpbb\log\dummy(), $this->config));  		$command = $application->find('cache:purge');  		$this->command_name = $command->getName(); diff --git a/tests/console/config/config_test.php b/tests/console/config/config_test.php index 7c098af004..076316217d 100644 --- a/tests/console/config/config_test.php +++ b/tests/console/config/config_test.php @@ -22,9 +22,14 @@ class phpbb_console_command_config_test extends phpbb_test_case  	public function setUp()  	{ +		global $phpbb_root_path, $phpEx; +  		$this->config = new \phpbb\config\config(array()); -		$this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$this->user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime') +		);  		$this->user->method('lang')->will($this->returnArgument(0));  	} diff --git a/tests/console/cron/cron_list_test.php b/tests/console/cron/cron_list_test.php index 22423304be..3bbe2078ba 100644 --- a/tests/console/cron/cron_list_test.php +++ b/tests/console/cron/cron_list_test.php @@ -32,7 +32,12 @@ class phpbb_console_command_cron_list_test extends phpbb_test_case  	protected function setUp()  	{ -		$this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$this->user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$this->user->method('lang')->will($this->returnArgument(0));  	} diff --git a/tests/console/cron/run_test.php b/tests/console/cron/run_test.php index f76e967484..b4a0203325 100644 --- a/tests/console/cron/run_test.php +++ b/tests/console/cron/run_test.php @@ -16,7 +16,6 @@ use Symfony\Component\Console\Tester\CommandTester;  use phpbb\console\command\cron\run;  require_once dirname(__FILE__) . '/tasks/simple.php'; -require_once dirname(__FILE__) . '/../../../phpBB/includes/functions.php';  class phpbb_console_command_cron_run_test extends phpbb_database_test_case  { @@ -39,10 +38,12 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case  		$db = $this->db = $this->new_dbal();  		$config = $this->config = new \phpbb\config\config(array('cron_lock' => '0')); -		set_config(null, null, null, $this->config);  		$this->lock = new \phpbb\lock\db('cron_lock', $this->config, $this->db); -		$this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$this->user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$this->user->method('lang')->will($this->returnArgument(0));  		$this->task = new phpbb_cron_task_simple(); @@ -76,6 +77,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case  		$this->assertSame(false, $this->lock->owns_lock());  	} +	/** +	 * @expectedException \phpbb\exception\runtime_exception +	 * @expectedExceptionMessage CRON_LOCK_ERROR +	 */  	public function test_error_lock()  	{  		$this->lock->acquire(); @@ -124,6 +129,10 @@ class phpbb_console_command_cron_run_test extends phpbb_database_test_case  		$this->assertSame(false, $this->lock->owns_lock());  	} +	/** +	 * @expectedException \phpbb\exception\runtime_exception +	 * @expectedExceptionMessage CRON_NO_SUCH_TASK +	 */  	public function test_arg_invalid()  	{  		$command_tester = $this->get_command_tester(); diff --git a/tests/console/fixtures/png.png b/tests/console/fixtures/png.png Binary files differnew file mode 100644 index 0000000000..c143a26a06 --- /dev/null +++ b/tests/console/fixtures/png.png diff --git a/tests/console/fixtures/thumbnail.xml b/tests/console/fixtures/thumbnail.xml new file mode 100644 index 0000000000..8037523633 --- /dev/null +++ b/tests/console/fixtures/thumbnail.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_attachments"> +		<column>attach_id</column> +		<column>physical_filename</column> +		<column>real_filename</column> +		<column>thumbnail</column> +		<column>extension</column> +		<column>mimetype</column> +		<column>attach_comment</column> + +		<row> +			<value>1</value> +			<value>test_png_1</value> +			<value>real_test.png</value> +			<value>0</value> +			<value>png</value> +			<value>image/png</value> +			<value></value> +		</row> +		<row> +			<value>2</value> +			<value>test_png_2</value> +			<value>real_test.png</value> +			<value>1</value> +			<value>png</value> +			<value>image/png</value> +			<value></value> +		</row> +		<row> +			<value>10</value> +			<value>test_txt</value> +			<value>real_test.txt</value> +			<value>0</value> +			<value>txt</value> +			<value>text/plain</value> +			<value></value> +		</row> +	</table> +</dataset> diff --git a/tests/console/fixtures/txt.txt b/tests/console/fixtures/txt.txt new file mode 100644 index 0000000000..a78c858f5c --- /dev/null +++ b/tests/console/fixtures/txt.txt @@ -0,0 +1,2 @@ +<HTML>mime trigger</HTML> +The HTML tags should remain uppercase so that case-insensitivity can be checked. diff --git a/tests/console/thumbnail_test.php b/tests/console/thumbnail_test.php new file mode 100644 index 0000000000..439e3623fa --- /dev/null +++ b/tests/console/thumbnail_test.php @@ -0,0 +1,122 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\thumbnail\generate; +use phpbb\console\command\thumbnail\delete; +use phpbb\console\command\thumbnail\recreate; + +class phpbb_console_command_thumbnail_test extends phpbb_database_test_case +{ +	protected $db; +	protected $config; +	protected $cache; +	protected $user; +	protected $phpEx; +	protected $phpbb_root_path; +	protected $application; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/thumbnail.xml'); +	} + +	public function setUp() +	{ +		global $config, $phpbb_root_path, $phpEx, $phpbb_filesystem; + +		if (!@extension_loaded('gd')) +		{ +			$this->markTestSkipped('Thumbnail tests require gd extension.'); +		} + +		parent::setUp(); + +		$config = $this->config = new \phpbb\config\config(array( +			'img_min_thumb_filesize' => 2, +			'img_max_thumb_width' => 2, +			'img_imagick' => '', +		)); + +		$this->db = $this->db = $this->new_dbal(); +		$this->user = $this->getMock('\phpbb\user', array(), array( +				new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +				'\phpbb\datetime') +		); +		$this->phpbb_root_path = $phpbb_root_path; +		$this->phpEx = $phpEx; + +		$this->cache = $this->getMock('\phpbb\cache\service', array(), array(new phpbb_mock_cache(), $this->config, $this->db, $this->phpbb_root_path, $this->phpEx)); +		$this->cache->expects(self::any())->method('obtain_attach_extensions')->will(self::returnValue(array( +			'png' => array('display_cat' => ATTACHMENT_CATEGORY_IMAGE), +			'txt' => array('display_cat' => ATTACHMENT_CATEGORY_NONE), +		))); + +		$this->application = new Application(); +		$this->application->add(new generate($this->user, $this->db, $this->cache, $this->phpbb_root_path, $this->phpEx)); +		$this->application->add(new delete($this->user, $this->db, $this->phpbb_root_path)); +		$this->application->add(new recreate($this->user)); + +		$phpbb_filesystem = new \phpbb\filesystem\filesystem(); + +		copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_1'); +		copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/test_png_2'); +		copy(dirname(__FILE__) . '/fixtures/png.png', $this->phpbb_root_path . 'files/thumb_test_png_2'); +		copy(dirname(__FILE__) . '/fixtures/txt.txt', $this->phpbb_root_path . 'files/test_txt'); +	} + +	protected function tearDown() +	{ +		parent::tearDown(); + +		unlink($this->phpbb_root_path . 'files/test_png_1'); +		unlink($this->phpbb_root_path . 'files/test_png_2'); +		unlink($this->phpbb_root_path . 'files/test_txt'); +		unlink($this->phpbb_root_path . 'files/thumb_test_png_1'); +		unlink($this->phpbb_root_path . 'files/thumb_test_png_2'); +	} + +	public function test_thumbnails() +	{ +		$command_tester = $this->get_command_tester('thumbnail:generate'); +		$exit_status = $command_tester->execute(array('command' => 'thumbnail:generate')); + +		self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); +		self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); +		self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); +		self::assertSame(0, $exit_status); + +		$command_tester = $this->get_command_tester('thumbnail:delete'); +		$exit_status = $command_tester->execute(array('command' => 'thumbnail:delete')); + +		self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); +		self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); +		self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); +		self::assertSame(0, $exit_status); + +		$command_tester = $this->get_command_tester('thumbnail:recreate'); +		$exit_status = $command_tester->execute(array('command' => 'thumbnail:recreate')); + +		self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_1')); +		self::assertSame(true, file_exists($this->phpbb_root_path . 'files/thumb_test_png_2')); +		self::assertSame(false, file_exists($this->phpbb_root_path . 'files/thumb_test_txt')); +		self::assertSame(0, $exit_status); +	} + +	public function get_command_tester($command_name) +	{ +		$command = $this->application->find($command_name); +		return new CommandTester($command); +	} +} diff --git a/tests/console/user/activate_test.php b/tests/console/user/activate_test.php new file mode 100644 index 0000000000..1588a76e47 --- /dev/null +++ b/tests/console/user/activate_test.php @@ -0,0 +1,86 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\user\activate; + +require_once dirname(__FILE__) . '/base.php'; + +class phpbb_console_user_activate_test extends phpbb_console_user_base +{ +	protected $notifications; + +	public function setUp() +	{ +		parent::setUp(); + +		$this->notifications = $this->getMockBuilder('\phpbb\notification\manager') +			->disableOriginalConstructor() +			->getMock(); +	} + +	public function get_command_tester() +	{ +		$application = new Application(); +		$application->add(new activate( +			$this->user, +			$this->db, +			$this->config, +			$this->language, +			$this->log, +			$this->notifications, +			$this->user_loader, +			$this->phpbb_root_path, +			$this->php_ext +		)); + +		$command = $application->find('user:activate'); +		$this->command_name = $command->getName(); + +		return new CommandTester($command); +	} + +	public function activate_test_data() +	{ +		return array( +			// Test an inactive user +			array('Test', false, 'USER_ADMIN_ACTIVATED'), +			array('Test', true, 'CLI_DESCRIPTION_USER_ACTIVATE_INACTIVE'), + +			// Test an active user +			array('Test 2', false, 'CLI_DESCRIPTION_USER_ACTIVATE_ACTIVE'), +			array('Test 2', true, 'USER_ADMIN_DEACTIVED'), + +			// Test a non existent user +			array('Foo', false, 'NO_USER'), +			array('Foo', true, 'NO_USER'), +		); +	} + +	/** +	 * @dataProvider activate_test_data +	 */ +	public function test_activate($username, $deactivate, $expected) +	{ +		$command_tester = $this->get_command_tester(); + +		$command_tester->execute(array( +			'command'		=> $this->command_name, +			'username'		=> $username, +			'--deactivate'	=> $deactivate, +		)); + +		$this->assertContains($expected, $command_tester->getDisplay()); +	} +} diff --git a/tests/console/user/add_test.php b/tests/console/user/add_test.php new file mode 100644 index 0000000000..8641bf87b6 --- /dev/null +++ b/tests/console/user/add_test.php @@ -0,0 +1,92 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\user\add; + +require_once dirname(__FILE__) . '/base.php'; + +class phpbb_console_user_add_test extends phpbb_console_user_base +{ +	public function get_command_tester() +	{ +		$application = new Application(); +		$application->add(new add( +			$this->user, +			$this->db, +			$this->config, +			$this->language, +			$this->passwords_manager, +			$this->phpbb_root_path, +			$this->php_ext +		)); + +		$command = $application->find('user:add'); +		$this->command_name = $command->getName(); +		$this->question = $command->getHelper('question'); +		return new CommandTester($command); +	} + +	public function test_add_no_dialog() +	{ +		$command_tester = $this->get_command_tester(); + +		$this->assertEquals(2, $this->get_user_id('Admin')); + +		$command_tester->execute(array( +			'command'		=> $this->command_name, +			'--username'	=> 'foo', +			'--password'	=> 'bar', +			'--email'		=> 'foo@test.com' +		)); + +		$this->assertNotEquals(null, $this->get_user_id('foo')); +		$this->assertContains('CLI_USER_ADD_SUCCESS', $command_tester->getDisplay()); +	} + +	public function test_add_dialog() +	{ +		$command_tester = $this->get_command_tester(); + +		$this->assertEquals(2, $this->get_user_id('Admin')); + +		$this->question->setInputStream($this->getInputStream("bar\npassword\npassword\nbar@test.com\n")); + +		$command_tester->execute(array( +			'command'		=> $this->command_name, +		)); + +		$this->assertNotEquals(null, $this->get_user_id('bar')); +		$this->assertContains('CLI_USER_ADD_SUCCESS', $command_tester->getDisplay()); + +	} + +	public function test_add_no_dialog_invalid() +	{ +		$command_tester = $this->get_command_tester(); + +		$this->assertEquals(3, $this->get_user_id('Test')); + +		$command_tester->execute(array( +			'command'		=> $this->command_name, +			'--username'	=> 'Test', +			'--password'	=> '1', +			'--email'		=> 'foo' +		)); + +		$this->assertContains('USERNAME_TAKEN', $command_tester->getDisplay()); +		$this->assertContains('TOO_SHORT', $command_tester->getDisplay()); +		$this->assertContains('EMAIL_INVALID', $command_tester->getDisplay()); +	} +} diff --git a/tests/console/user/base.php b/tests/console/user/base.php new file mode 100644 index 0000000000..b84c0bb267 --- /dev/null +++ b/tests/console/user/base.php @@ -0,0 +1,121 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +abstract class phpbb_console_user_base extends phpbb_database_test_case +{ +	protected $db; +	protected $config; +	protected $user; +	protected $language; +	protected $log; +	protected $passwords_manager; +	protected $command_name; +	protected $question; +	protected $user_loader; +	protected $phpbb_root_path; +	protected $php_ext; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config.xml'); +	} + +	public function setUp() +	{ +		global $auth, $db, $cache, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path, $phpEx; + +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		$phpbb_container = new phpbb_mock_container_builder(); +		$phpbb_container->set('cache.driver', new phpbb_mock_cache()); +		$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); + +		$auth = $this->getMock('\phpbb\auth\auth'); + +		$cache = $phpbb_container->get('cache.driver'); + +		$config = $this->config = new \phpbb\config\config(array( +			'board_timezone'	=> 'UTC', +			'default_lang'		=> 'en', +			'email_enable'		=> false, +			'min_name_chars'	=> 3, +			'max_name_chars'	=> 10, +			'min_pass_chars'	=> 3, +			'max_pass_chars'	=> 10, +			'pass_complex'		=> 'PASS_TYPE_ANY', +		)); + +		$db = $this->db = $this->new_dbal(); + +		$this->language = $this->getMockBuilder('\phpbb\language\language') +			->disableOriginalConstructor() +			->getMock(); +		$this->language->expects($this->any()) +			->method('lang') +			->will($this->returnArgument(0)); +		$user = $this->user = $this->getMock('\phpbb\user', array(), array( +			$this->language, +			'\phpbb\datetime' +		)); + +		$this->user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE); + +		$driver_helper = new \phpbb\passwords\driver\helper($this->config); +		$passwords_drivers = array( +			'passwords.driver.bcrypt_2y'	=> new \phpbb\passwords\driver\bcrypt_2y($this->config, $driver_helper), +			'passwords.driver.bcrypt'		=> new \phpbb\passwords\driver\bcrypt($this->config, $driver_helper), +			'passwords.driver.salted_md5'	=> new \phpbb\passwords\driver\salted_md5($this->config, $driver_helper), +			'passwords.driver.phpass'		=> new \phpbb\passwords\driver\phpass($this->config, $driver_helper), +		); + +		$passwords_helper = new \phpbb\passwords\helper; +		$this->passwords_manager = new \phpbb\passwords\manager($this->config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); + +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $phpEx; + +		$this->log = $this->getMockBuilder('\phpbb\log\log') +			->disableOriginalConstructor() +			->getMock(); + +		$phpbb_container->set('auth.provider.db', new phpbb_mock_auth_provider()); +		$provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config); +		$provider_collection->add('auth.provider.db'); +		$phpbb_container->set( +			'auth.provider_collection', +			$provider_collection +		); + +		parent::setUp(); +	} + +	public function get_user_id($username) +	{ +		$sql = 'SELECT user_id +			FROM ' . USERS_TABLE . ' +			WHERE ' . 'username = ' . "'" . $username . "'"; +		$result = $this->db->sql_query($sql); +		$row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		return $row['user_id']; +	} + +	public function getInputStream($input) +	{ +		$stream = fopen('php://memory', 'r+', false); +		fputs($stream, $input); +		rewind($stream); + +		return $stream; +	} +} diff --git a/tests/console/user/delete_test.php b/tests/console/user/delete_test.php new file mode 100644 index 0000000000..88f91afab1 --- /dev/null +++ b/tests/console/user/delete_test.php @@ -0,0 +1,93 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\user\delete; + +require_once dirname(__FILE__) . '/base.php'; + +class phpbb_console_user_delete_test extends phpbb_console_user_base +{ +	public function get_command_tester() +	{ +		$application = new Application(); +		$application->add(new delete( +			$this->user, +			$this->db, +			$this->language, +			$this->log, +			$this->user_loader, +			$this->phpbb_root_path, +			$this->php_ext +		)); + +		$command = $application->find('user:delete'); +		$this->command_name = $command->getName(); +		$this->question = $command->getHelper('question'); + +		return new CommandTester($command); +	} + +	public function test_delete() +	{ +		$command_tester = $this->get_command_tester(); + +		$this->assertEquals(3, $this->get_user_id('Test')); + +		$this->question->setInputStream($this->getInputStream("yes\n")); + +		$command_tester->execute(array( +			'command'			=> $this->command_name, +			'username'			=> 'Test', +			'--delete-posts'	=> false, +		)); + +		$this->assertNull($this->get_user_id('Test')); +		$this->assertContains('USER_DELETED', $command_tester->getDisplay()); +	} + +	public function test_delete_non_user() +	{ +		$command_tester = $this->get_command_tester(); + +		$this->assertNull($this->get_user_id('Foo')); + +		$this->question->setInputStream($this->getInputStream("yes\n")); + +		$command_tester->execute(array( +			'command'			=> $this->command_name, +			'username'			=> 'Foo', +			'--delete-posts'	=> false, +		)); + +		$this->assertContains('NO_USER', $command_tester->getDisplay()); +	} + +	public function test_delete_cancel() +	{ +		$command_tester = $this->get_command_tester(); + +		$this->assertEquals(3, $this->get_user_id('Test')); + +		$this->question->setInputStream($this->getInputStream("no\n")); + +		$command_tester->execute(array( +			'command'			=> $this->command_name, +			'username'			=> 'Test', +			'--delete-posts'	=> false, +		)); + +		$this->assertNotNull($this->get_user_id('Test')); +	} +} diff --git a/tests/console/user/fixtures/config.xml b/tests/console/user/fixtures/config.xml new file mode 100644 index 0000000000..a988ba463f --- /dev/null +++ b/tests/console/user/fixtures/config.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_users"> +		<column>user_id</column> +		<column>user_permissions</column> +		<column>username</column> +		<column>username_clean</column> +		<column>user_sig</column> +		<column>user_type</column> +		<row> +			<value>1</value> +			<value></value> +			<value>Guest</value> +			<value>guest</value> +			<value></value> +			<value>0</value> +		</row> +		<row> +			<value>2</value> +			<value></value> +			<value>Admin</value> +			<value>admin</value> +			<value></value> +			<value>3</value> +		</row> +		<row> +			<value>3</value> +			<value></value> +			<value>Test</value> +			<value>test</value> +			<value></value> +			<value>1</value> +		</row> +		<row> +			<value>4</value> +			<value></value> +			<value>Test 2</value> +			<value>test 2</value> +			<value></value> +			<value>0</value> +		</row> +		<row> +			<value>5</value> +			<value></value> +			<value>Test Unclean</value> +			<value>Test Unclean</value> +			<value></value> +			<value>0</value> +		</row> +	</table> +	<table name="phpbb_groups"> +		<column>group_id</column> +		<column>group_name</column> +		<column>group_type</column> +		<column>group_desc</column> +		<row> +			<value>1</value> +			<value>REGISTERED</value> +			<value>3</value> +			<value>foobar</value> +		</row> +	</table> +</dataset> diff --git a/tests/console/user/reclean_test.php b/tests/console/user/reclean_test.php new file mode 100644 index 0000000000..1bf0b8ef5a --- /dev/null +++ b/tests/console/user/reclean_test.php @@ -0,0 +1,49 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use phpbb\console\command\user\reclean; + +require_once dirname(__FILE__) . '/base.php'; + +class phpbb_console_user_reclean_test extends phpbb_console_user_base +{ +	public function get_command_tester() +	{ +		$application = new Application(); +		$application->add(new reclean( +			$this->user, +			$this->db, +			$this->language +		)); + +		$command = $application->find('user:reclean'); +		$this->command_name = $command->getName(); + +		return new CommandTester($command); +	} + +	public function test_reclean() +	{ +		$command_tester = $this->get_command_tester(); + +		$exit_status = $command_tester->execute(array('command' => $this->command_name)); +		$this->assertSame(0, $exit_status); + +		$result = $this->db->sql_query('SELECT user_id FROM ' . USERS_TABLE . " WHERE username_clean = 'test unclean'"); +		$row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); +		$this->assertNotNull($row['user_id']); +	} +} diff --git a/tests/content_visibility/delete_post_test.php b/tests/content_visibility/delete_post_test.php index 6ad6351a0c..4ea95b0a96 100644 --- a/tests/content_visibility/delete_post_test.php +++ b/tests/content_visibility/delete_post_test.php @@ -11,11 +11,8 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  require_once dirname(__FILE__) . '/../mock/search.php';  class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case @@ -292,12 +289,14 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case  	{  		global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx; -		$config['search_type'] = 'phpbb_mock_search'; +		$config = new \phpbb\config\config(array( +			'num_posts' => 3, +			'num_topics' => 1, +			'search_type' => 'phpbb_mock_search', +		));  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$phpbb_config = new \phpbb\config\config(array('num_posts' => 3, 'num_topics' => 1));  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		set_config_count(null, null, null, $phpbb_config);  		// Create auth mock  		$auth = $this->getMock('\phpbb\auth\auth'); @@ -307,13 +306,18 @@ class phpbb_content_visibility_delete_post_test extends phpbb_database_test_case  			->will($this->returnValueMap(array(  				array('m_approve', 1, true),  			))); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$attachment_delete = new \phpbb\attachment\delete($config, $db, new \phpbb_mock_event_dispatcher(), new \phpbb\filesystem\filesystem(), new \phpbb\attachment\resync($db), $phpbb_root_path);  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$phpbb_container = new phpbb_mock_container_builder();  		$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); -		$phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $phpbb_config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); +		$phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); +		// Works as a workaround for tests +		$phpbb_container->set('attachment.manager', $attachment_delete);  		delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $reason); diff --git a/tests/content_visibility/get_forums_visibility_sql_test.php b/tests/content_visibility/get_forums_visibility_sql_test.php index 28e463ecb5..6c5066119e 100644 --- a/tests/content_visibility/get_forums_visibility_sql_test.php +++ b/tests/content_visibility/get_forums_visibility_sql_test.php @@ -134,7 +134,9 @@ class phpbb_content_visibility_get_forums_visibility_sql_test extends phpbb_data  			->method('acl_getf')  			->with($this->stringContains('_'), $this->anything())  			->will($this->returnValueMap($permissions)); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$config = new phpbb\config\config(array());  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/get_global_visibility_sql_test.php b/tests/content_visibility/get_global_visibility_sql_test.php index 586bae8668..9ae4182673 100644 --- a/tests/content_visibility/get_global_visibility_sql_test.php +++ b/tests/content_visibility/get_global_visibility_sql_test.php @@ -134,7 +134,9 @@ class phpbb_content_visibility_get_global_visibility_sql_test extends phpbb_data  			->method('acl_getf')  			->with($this->stringContains('_'), $this->anything())  			->will($this->returnValueMap($permissions)); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$config = new phpbb\config\config(array());  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/get_visibility_sql_test.php b/tests/content_visibility/get_visibility_sql_test.php index 9ae2d2fdc4..aaaf64330e 100644 --- a/tests/content_visibility/get_visibility_sql_test.php +++ b/tests/content_visibility/get_visibility_sql_test.php @@ -81,7 +81,9 @@ class phpbb_content_visibility_get_visibility_sql_test extends phpbb_database_te  			->method('acl_get')  			->with($this->stringContains('_'), $this->anything())  			->will($this->returnValueMap($permissions)); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$config = new phpbb\config\config(array());  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/set_post_visibility_test.php b/tests/content_visibility/set_post_visibility_test.php index 36ebf58374..e33a1f30d5 100644 --- a/tests/content_visibility/set_post_visibility_test.php +++ b/tests/content_visibility/set_post_visibility_test.php @@ -11,11 +11,8 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_test_case  { @@ -124,7 +121,9 @@ class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_t  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal();  		$auth = $this->getMock('\phpbb\auth\auth'); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$config = new phpbb\config\config(array());  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); @@ -175,7 +174,9 @@ class phpbb_content_visibility_set_post_visibility_test extends phpbb_database_t  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal();  		$auth = $this->getMock('\phpbb\auth\auth'); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$config = new phpbb\config\config(array());  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/content_visibility/set_topic_visibility_test.php b/tests/content_visibility/set_topic_visibility_test.php index 6c34f42167..78431396c3 100644 --- a/tests/content_visibility/set_topic_visibility_test.php +++ b/tests/content_visibility/set_topic_visibility_test.php @@ -11,11 +11,8 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  class phpbb_content_visibility_set_topic_visibility_test extends phpbb_database_test_case  { @@ -88,7 +85,9 @@ class phpbb_content_visibility_set_topic_visibility_test extends phpbb_database_  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal();  		$auth = $this->getMock('\phpbb\auth\auth'); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$config = new phpbb\config\config(array());  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$content_visibility = new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE); diff --git a/tests/controller/common_helper_route.php b/tests/controller/common_helper_route.php index ea77a289c9..367c15a667 100644 --- a/tests/controller/common_helper_route.php +++ b/tests/controller/common_helper_route.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  use Symfony\Component\Routing\Generator\UrlGeneratorInterface;  abstract class phpbb_controller_common_helper_route extends phpbb_test_case @@ -27,6 +25,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	private   $provider;  	private   $filesystem;  	private   $phpbb_path_helper; +	private   $helper; +	private   $router; +	private   $routing_helper;  	public function setUp()  	{ @@ -44,10 +45,6 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  		);  		$this->generate_route_objects();  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher; -		$this->user = new \phpbb\user('\phpbb\datetime'); - -		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); -		$this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $this->user, new \phpbb\template\context());  	}  	protected function get_phpbb_root_path() @@ -91,7 +88,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  		$this->symfony_request = new \phpbb\symfony_request(  			$this->request  		); -		$this->filesystem = new \phpbb\filesystem(); +		$this->filesystem = new \phpbb\filesystem\filesystem();  		$this->phpbb_path_helper = new \phpbb\path_helper(  			$this->symfony_request,  			$this->filesystem, @@ -100,15 +97,50 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			$phpEx  		); -		$finder = new \phpbb\finder( -			new \phpbb\filesystem(), +		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$this->user = new \phpbb\user($lang, '\phpbb\datetime');; + +		$container = new phpbb_mock_container_builder(); +		$container->setParameter('core.environment', PHPBB_ENVIRONMENT); +		$cache_path = $phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader($this->filesystem, ''); +		$twig = new \phpbb\template\twig\environment( +			$this->config, +			$this->filesystem, +			$this->phpbb_path_helper, +			$cache_path, +			null, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		); +		$this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig)); + +		$this->extension_manager = new phpbb_mock_extension_manager(  			dirname(__FILE__) . '/', -			new phpbb_mock_cache() +			array( +				'vendor2/foo' => array( +					'ext_name' => 'vendor2/foo', +					'ext_active' => '1', +					'ext_path' => 'ext/vendor2/foo/', +				), +			) +		); + +		$loader = new \Symfony\Component\Routing\Loader\YamlFileLoader( +			new \phpbb\routing\file_locator($this->filesystem, dirname(__FILE__) . '/')  		); -		$finder->set_extensions(array_keys($this->extension_manager->all_enabled())); -		$this->provider = new \phpbb\controller\provider(); -		$this->provider->find_routing_files($finder); -		$this->provider->find(dirname(__FILE__) . '/'); +		$resources_locator = new \phpbb\routing\resources_locator\default_resources_locator(dirname(__FILE__) . '/', PHPBB_ENVIRONMENT, $this->extension_manager); +		$this->router = new phpbb_mock_router($container, $resources_locator, $loader, dirname(__FILE__) . '/', 'php'); +  		// Set correct current phpBB root path  		$this->root_path = $this->get_phpbb_root_path();  	} @@ -140,6 +172,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, '/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, '/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, '/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false, '/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -148,8 +183,10 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	*/  	public function test_helper_url_no_rewrite($route, $params, $is_amp, $session_id, $expected, $description)  	{ -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id), $description); +		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description);  	}  	public function helper_url_data_with_rewrite() @@ -179,6 +216,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, '/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, '/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, '/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false, '/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -188,8 +228,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	public function test_helper_url_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)  	{  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id), $description); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id), $description);  	}  	public function helper_url_data_absolute() @@ -219,6 +260,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -228,8 +272,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	public function test_helper_url_absolute($route, $params, $is_amp, $session_id, $expected, $description)  	{  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description);  	}  	public function helper_url_data_relative_path() @@ -259,6 +304,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, 'app.php/foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, 'app.php/foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, 'app.php/foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false,  'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -268,8 +316,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	public function test_helper_url_relative_path($route, $params, $is_amp, $session_id, $expected, $description)  	{  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description);  	}  	public function helper_url_data_network() @@ -299,6 +348,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false, '//localhost/' . $this->path_to_app() . 'app.php/foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -308,10 +360,11 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	public function test_helper_url_network($route, $params, $is_amp, $session_id, $expected, $description)  	{  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '0')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description);  	} -//TODO +  	public function helper_url_data_absolute_with_rewrite()  	{  		return array( @@ -339,6 +392,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false, 'http://localhost/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -348,8 +404,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	public function test_helper_url_absolute_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)  	{  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::ABSOLUTE_URL), $description);  	}  	public function helper_url_data_relative_path_with_rewrite() @@ -388,8 +445,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	public function test_helper_url_relative_path_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)  	{  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::RELATIVE_PATH), $description);  	}  	public function helper_url_data_network_with_rewrite() @@ -419,6 +477,9 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array('controller2', array(), true, false, '//localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),  			array('controller2', array(), false, false, '//localhost/' . $this->path_to_app() . 'foo/bar', 'no params using empty array'),  			array('controller3', array('p' => 3), true, false, '//localhost/' . $this->path_to_app() . 'foo/bar/p-3', 'no params using empty array'), + +			// Resolves DI parameters +			array('controller4', array(), true, false, '//localhost/' . $this->path_to_app() . 'foo/' . PHPBB_ENVIRONMENT, 'di parameter'),  		);  	} @@ -427,9 +488,10 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  	 */  	public function test_helper_url_network_with_rewrite($route, $params, $is_amp, $session_id, $expected, $description)  	{ -		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description); +		$this->config = new \phpbb\config\config(['enable_mod_rewrite' => '1']); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route($route, $params, $is_amp, $session_id, UrlGeneratorInterface::NETWORK_PATH), $description);  	}  	public function helper_url_data_force_server_vars() @@ -442,8 +504,7 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			array(false, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::ABSOLUTE_PATH, '/my/board/app.php/foo'),  			array(true, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::ABSOLUTE_PATH, '/my/board/foo'),  			array(false, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::RELATIVE_PATH, 'app.php/foo'), -			array(true, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::RELATIVE_PATH, 'foo'), -		); +			array(true, true, 'my_server', 443, '/my/board', 'http://', UrlGeneratorInterface::RELATIVE_PATH, 'foo'),		);  	}  	/** @@ -460,8 +521,8 @@ abstract class phpbb_controller_common_helper_route extends phpbb_test_case  			'server_protocol' => $server_protocol,  		)); -		$helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->provider, $this->extension_manager, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php', dirname(__FILE__) . '/'); -		static::assertEquals($expected, $helper->route('controller1', array(), false, false, $type)); - +		$this->routing_helper = new \phpbb\routing\helper($this->config, $this->router, $this->symfony_request, $this->request, $this->filesystem, $this->root_path, 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $this->symfony_request, $this->request, $this->routing_helper); +		static::assertEquals($expected, $this->helper->route('controller1', array(), false, false, $type));  	}  } diff --git a/tests/controller/config/routing.yml b/tests/controller/config/test/routing/environment.yml index 1e7df02684..1e7df02684 100644 --- a/tests/controller/config/routing.yml +++ b/tests/controller/config/test/routing/environment.yml diff --git a/tests/controller/controller_test.php b/tests/controller/controller_test.php index 62feee3fed..d921d0eade 100644 --- a/tests/controller/controller_test.php +++ b/tests/controller/controller_test.php @@ -11,7 +11,8 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +include_once(__DIR__ . '/ext/vendor2/foo/controller.php'); +include_once(__DIR__.'/phpbb/controller/foo.php');  use Symfony\Component\HttpFoundation\Request;  use Symfony\Component\Config\FileLocator; @@ -30,14 +31,25 @@ class phpbb_controller_controller_test extends phpbb_test_case  					'ext_active' => '1',  					'ext_path' => 'ext/vendor2/foo/',  				), +				'vendor2/bar' => array( +					'ext_name' => 'vendor2/bar', +					'ext_active' => '1', +					'ext_path' => 'ext/vendor2/bar/', +				),  			));  	} -	public function test_provider() +	public function test_router_default_loader()  	{ -		$provider = new \phpbb\controller\provider(); -		$provider->find_routing_files($this->extension_manager->get_finder()); -		$routes = $provider->find(__DIR__)->get_routes(); +		$container = new phpbb_mock_container_builder(); +		$container->setParameter('core.environment', PHPBB_ENVIRONMENT); + +		$loader = new \Symfony\Component\Routing\Loader\YamlFileLoader( +			new \phpbb\routing\file_locator(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/') +		); +		$resources_locator = new \phpbb\routing\resources_locator\default_resources_locator(dirname(__FILE__) . '/', PHPBB_ENVIRONMENT, $this->extension_manager); +		$router = new phpbb_mock_router($container, $resources_locator, $loader, dirname(__FILE__) . '/', 'php'); +		$routes = $router->get_routes();  		// This will need to be updated if any new routes are defined  		$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('core_controller')); @@ -49,10 +61,13 @@ class phpbb_controller_controller_test extends phpbb_test_case  		$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('controller2'));  		$this->assertEquals('/foo/bar', $routes->get('controller2')->getPath()); +		$this->assertInstanceOf('Symfony\Component\Routing\Route', $routes->get('controller3')); +		$this->assertEquals('/bar', $routes->get('controller3')->getPath()); +  		$this->assertNull($routes->get('controller_noroute'));  	} -	public function test_controller_resolver() +	protected function get_foo_container()  	{  		$container = new ContainerBuilder();  		// YamlFileLoader only uses one path at a time, so we need to loop @@ -63,26 +78,59 @@ class phpbb_controller_controller_test extends phpbb_test_case  			$loader->load('services.yml');  		} -		// Autoloading classes within the tests folder does not work -		// so I'll include them manually. -		if (!class_exists('vendor2\\foo\\controller')) -		{ -			include(__DIR__ . '/ext/vendor2/foo/controller.php'); -		} -		if (!class_exists('phpbb\\controller\\foo')) -		{ -			include(__DIR__.'/phpbb/controller/foo.php'); -		} +		return $container; +	} -		$resolver = new \phpbb\controller\resolver(new \phpbb\user('\phpbb\datetime'), $container, dirname(__FILE__) . '/'); +	public function test_controller_resolver() +	{ +		$container = $this->get_foo_container(); + +		$resolver = new \phpbb\controller\resolver($container, dirname(__FILE__) . '/');  		$symfony_request = new Request();  		$symfony_request->attributes->set('_controller', 'foo.controller:handle');  		$this->assertEquals($resolver->getController($symfony_request), array(new foo\controller, 'handle')); +		$this->assertEquals(array('foo'), $resolver->getArguments($symfony_request, $resolver->getController($symfony_request)));  		$symfony_request = new Request();  		$symfony_request->attributes->set('_controller', 'core_foo.controller:bar');  		$this->assertEquals($resolver->getController($symfony_request), array(new phpbb\controller\foo, 'bar')); +		$this->assertEquals(array(), $resolver->getArguments($symfony_request, $resolver->getController($symfony_request))); +	} + +	public function data_get_arguments() +	{ +		return array( +			array(array(new foo\controller(), 'handle2'), array('foo', 0)), +			array(array(new foo\controller(), 'handle_fail'), array('default'), array('no_default' => 'default')), +			array(new foo\controller(), array(), array()), +			array(array(new foo\controller(), 'handle_fail'), array(), array(), '\phpbb\controller\exception', 'CONTROLLER_ARGUMENT_VALUE_MISSING'), +			array('', array(), array(), '\ReflectionException', 'Function () does not exist'), +			array(new phpbb\controller\foo, array(), array(), '\ReflectionException', 'Method __invoke does not exist'), +		); +	} + +	/** +	 * @dataProvider data_get_arguments +	 */ +	public function test_get_arguments($input, $expected, $set_attributes = array(), $exception = '', $exception_message = '') +	{ +		$container = $this->get_foo_container(); + +		$resolver = new \phpbb\controller\resolver($container, dirname(__FILE__) . '/'); +		$symfony_request = new Request(); + +		foreach ($set_attributes as $name => $value) +		{ +			$symfony_request->attributes->set($name, $value); +		} + +		if (!empty($exception)) +		{ +			$this->setExpectedException($exception, $exception_message); +		} + +		$this->assertEquals($expected, $resolver->getArguments($symfony_request, $input));  	}  } diff --git a/tests/controller/ext/vendor2/bar/config/services.yml b/tests/controller/ext/vendor2/bar/config/services.yml new file mode 100644 index 0000000000..05a8a1994d --- /dev/null +++ b/tests/controller/ext/vendor2/bar/config/services.yml @@ -0,0 +1,3 @@ +services: +    bar.controller: +        class: bar\controller diff --git a/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml b/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml new file mode 100644 index 0000000000..5696ecb180 --- /dev/null +++ b/tests/controller/ext/vendor2/bar/config/test/routing/environment.yml @@ -0,0 +1,3 @@ +controller3: +    path: /bar +    defaults: { _controller: bar.controller:handle } diff --git a/tests/controller/ext/vendor2/bar/controller.php b/tests/controller/ext/vendor2/bar/controller.php new file mode 100644 index 0000000000..ad35f5a051 --- /dev/null +++ b/tests/controller/ext/vendor2/bar/controller.php @@ -0,0 +1,18 @@ +<?php + +namespace bar; + +use Symfony\Component\HttpFoundation\Response; + +class controller +{ +	/** +	* Handle method +	* +	* @return null +	*/ +	public function handle() +	{ +		return new Response('Test', 200); +	} +} diff --git a/tests/controller/ext/vendor2/foo/config/routing.yml b/tests/controller/ext/vendor2/foo/config/routing.yml index e3e8ee5f98..7d4ac7be93 100644 --- a/tests/controller/ext/vendor2/foo/config/routing.yml +++ b/tests/controller/ext/vendor2/foo/config/routing.yml @@ -5,3 +5,7 @@ controller1:  include_controller2:      resource: "routing_2.yml"      prefix:   /foo + +controller4: +    path: /foo/%core.environment% +    defaults: { _controller: foo.controller:handle } diff --git a/tests/controller/ext/vendor2/foo/controller.php b/tests/controller/ext/vendor2/foo/controller.php index ce2233b3c9..cabcae042b 100644 --- a/tests/controller/ext/vendor2/foo/controller.php +++ b/tests/controller/ext/vendor2/foo/controller.php @@ -11,8 +11,23 @@ class controller  	*  	* @return null  	*/ -	public function handle() +	public function handle($optional = 'foo')  	{  		return new Response('Test', 200);  	} + +	public function handle2($foo = 'foo', $very_optional = 0) +	{ +		return new Response('Test2', 200); +	} + +	public function handle_fail($no_default) +	{ +		return new Response('Test_fail', 200); +	} + +	public function __invoke() +	{ +		$this->handle(); +	}  } diff --git a/tests/controller/helper_route_adm_subdir_test.php b/tests/controller/helper_route_adm_subdir_test.php index f27ac81b04..a1bf1b8805 100644 --- a/tests/controller/helper_route_adm_subdir_test.php +++ b/tests/controller/helper_route_adm_subdir_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/common_helper_route.php';  class phpbb_controller_helper_route_adm_subdir_test extends phpbb_controller_common_helper_route diff --git a/tests/controller/helper_route_adm_test.php b/tests/controller/helper_route_adm_test.php index 86dc36ef1f..6ee394eaaa 100644 --- a/tests/controller/helper_route_adm_test.php +++ b/tests/controller/helper_route_adm_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/common_helper_route.php';  class phpbb_controller_helper_route_adm_test extends phpbb_controller_common_helper_route diff --git a/tests/controller/helper_route_root_test.php b/tests/controller/helper_route_root_test.php index 63a2f2f8f7..12462e076d 100644 --- a/tests/controller/helper_route_root_test.php +++ b/tests/controller/helper_route_root_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/common_helper_route.php';  class phpbb_controller_helper_route_test extends phpbb_controller_common_helper_route diff --git a/tests/controller/helper_route_slash_test.php b/tests/controller/helper_route_slash_test.php index 3db5ec19e5..c781a6943e 100644 --- a/tests/controller/helper_route_slash_test.php +++ b/tests/controller/helper_route_slash_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/common_helper_route.php';  class phpbb_controller_helper_route_slash_test extends phpbb_controller_common_helper_route diff --git a/tests/controller/helper_route_unclean_path_test.php b/tests/controller/helper_route_unclean_path_test.php index 9d8b62bc1c..80f1a99fff 100644 --- a/tests/controller/helper_route_unclean_path_test.php +++ b/tests/controller/helper_route_unclean_path_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/common_helper_route.php';  class phpbb_controller_helper_route_unclean_path_test extends phpbb_controller_common_helper_route diff --git a/tests/datetime/from_format_test.php b/tests/datetime/from_format_test.php index 8968619bb5..7ecb546768 100644 --- a/tests/datetime/from_format_test.php +++ b/tests/datetime/from_format_test.php @@ -37,7 +37,11 @@ class phpbb_datetime_from_format_test extends phpbb_test_case  	*/  	public function test_from_format($timezone, $format, $expected)  	{ -		$user = new \phpbb\user('\phpbb\datetime'); +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->timezone = new DateTimeZone($timezone);  		$user->lang['datetime'] = array(  			'TODAY'		=> 'Today', @@ -107,7 +111,11 @@ class phpbb_datetime_from_format_test extends phpbb_test_case  	 */  	public function test_relative_format_date($timestamp, $forcedate, $expected)  	{ -		$user = new \phpbb\user('\phpbb\datetime'); +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->timezone = new DateTimeZone('UTC');  		$user->lang['datetime'] = array(  			'TODAY'		=> 'Today', diff --git a/tests/dbal/auto_increment_test.php b/tests/dbal/auto_increment_test.php index 1ed8ea29e3..950a4fc8f7 100644 --- a/tests/dbal/auto_increment_test.php +++ b/tests/dbal/auto_increment_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_auto_increment_test extends phpbb_database_test_case  {  	protected $db; @@ -30,7 +28,8 @@ class phpbb_dbal_auto_increment_test extends phpbb_database_test_case  		parent::setUp();  		$this->db = $this->new_dbal(); -		$this->tools = new \phpbb\db\tools($this->db); +		$factory = new \phpbb\db\tools\factory(); +		$this->tools = $factory->get($this->db);  		$this->table_data = array(  			'COLUMNS'		=> array( diff --git a/tests/dbal/boolean_processor_test.php b/tests/dbal/boolean_processor_test.php new file mode 100644 index 0000000000..c69f60a1a8 --- /dev/null +++ b/tests/dbal/boolean_processor_test.php @@ -0,0 +1,321 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_boolean_processor_test extends phpbb_database_test_case +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/boolean_processor.xml'); +	} + +	public function test_single_not_like() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +			), +			'WHERE'		=> array('u.username_clean', 'NOT_LIKE', 'gr' . $db->get_any_char()), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('user_id' => '1'), +			array('user_id' => '2'), +			array('user_id' => '3'), +			array('user_id' => '6'), +			), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} + +	public function test_single_like() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +			), +			'WHERE'		=> array('u.username_clean', 'LIKE', 'gr' . $db->get_any_char()), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('user_id' => '4'), +			array('user_id' => '5'), +			), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} + +	public function test_single_not_in() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +			), +			'WHERE'		=> array('u.user_id', 'NOT_IN', array(3,4,5)), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('user_id' => '1'), +			array('user_id' => '2'), +			array('user_id' => '6'), +			), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} + +	public function test_single_in() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +			), +			'WHERE'		=> array('u.user_id', 'IN', array(3,4,5)), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('user_id' => '3'), +			array('user_id' => '4'), +			array('user_id' => '5'), +			), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} + +	public function test_and_of_or_of_and() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +				'phpbb_user_group'	=> 'ug', +			), +			'LEFT_JOIN'	=> array( +				array( +					'FROM'	=> array( +						'phpbb_banlist'	=> 'b', +					), +					'ON'	=> 'u.user_id = b.ban_userid', +				), +			), +			'WHERE'		=> array('AND', +				array( +					array('OR', +						array( +							array('AND', +								array( +									array('ug.user_id', 'IN', array(1, 2, 3, 4)), +									array('ug.group_id', '=', 2), +								), +							), +							array('AND', +								array( +									array('ug.group_id', '=', 1), +									array('b.ban_id', 'IS_NOT', NULL), +								), +							), +						), +					), +					array('u.user_id', '=', 'ug.user_id'), +				), +			), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('user_id' => '2'), +			array('user_id' => '4'), +			), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} + +	public function test_triple_and_with_in() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +				'phpbb_user_group'	=> 'ug', +			), +			'WHERE'		=> array('AND', +				array( +					array('ug.user_id', 'IN', array(1, 2, 3, 4)), +					array('ug.group_id', '=', 1), +					array('u.user_id', '=', 'ug.user_id'), +				), +			), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('user_id' => '1'), +			array('user_id' => '2'), +			array('user_id' => '3'), +			), $db->sql_fetchrowset($result), +			($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +		); + +	} + +	public function test_double_and_with_not_of_or() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.user_id', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +				'phpbb_user_group'	=> 'ug', +			), +			'WHERE'		=> array('AND', +				array( +					array('NOT', +						array( +							array('OR', +								array( +									array('ug.group_id', '=', 1), +									array('ug.group_id', '=', 2), +								), +							), +						), +					), +					array('u.user_id', '=', 'ug.user_id'), +				), +			), +			'ORDER_BY'	=> 'u.user_id', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array(), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} + +	public function test_triple_and_with_is_null() +	{ +		$db = $this->new_dbal(); + +		$db->sql_return_on_error(true); + +		$sql_ary = array( +			'SELECT'	=> 'u.username', +			'FROM'		=> array( +				'phpbb_users'		=> 'u', +				'phpbb_user_group'	=> 'ug', +			), +			'LEFT_JOIN'	=> array( +				array( +					'FROM'	=> array( +						'phpbb_banlist'	=> 'b', +					), +					'ON'	=> 'u.user_id = b.ban_userid', +				), +			), +			'WHERE'		=> array('AND', +				array( +					array('ug.group_id', '=', 1), +					array('u.user_id', '=', 'ug.user_id'), +					array('b.ban_id', 'IS', NULL), +				), +			), +			'ORDER_BY'	=> 'u.username', +		); +		$sql = $db->sql_build_query('SELECT', $sql_ary); +		$result = $db->sql_query($sql); + +		$db->sql_return_on_error(false); + +		$this->assertEquals(array( +			array('username' => 'helper'), +			array('username' => 'mass email'), +			), $db->sql_fetchrowset($result), +				($result === false) ? +				"SQL ERROR:<br>" . var_export($sql, true) . "<br>" . $db->sql_error() : +				var_export($sql, true) . '   ' . var_export($result, true) +			); +	} +} diff --git a/tests/dbal/connect_test.php b/tests/dbal/connect_test.php index 1ae34bd2b6..3933dab798 100644 --- a/tests/dbal/connect_test.php +++ b/tests/dbal/connect_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_connect_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -22,7 +20,9 @@ class phpbb_dbal_connect_test extends phpbb_database_test_case  	public function test_failing_connect()  	{ -		global $phpbb_root_path, $phpEx; +		global $phpbb_root_path, $phpEx, $phpbb_filesystem; + +		$phpbb_filesystem = new phpbb\filesystem\filesystem();  		$config = $this->get_database_config(); diff --git a/tests/dbal/cross_join_test.php b/tests/dbal/cross_join_test.php index 7ba937ccc6..be9258c58b 100644 --- a/tests/dbal/cross_join_test.php +++ b/tests/dbal/cross_join_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_dbal_cross_join_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index 5832b966d8..b884b4ab95 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -11,13 +11,11 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_db_tools_test extends phpbb_database_test_case  {  	/** @var \phpbb\db\driver\driver_interface */  	protected $db; -	/** @var \phpbb\db\tools */ +	/** @var \phpbb\db\tools\tools_interface */  	protected $tools;  	protected $table_exists;  	protected $table_data; @@ -32,7 +30,8 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case  		parent::setUp();  		$this->db = $this->new_dbal(); -		$this->tools = new \phpbb\db\tools($this->db); +		$factory = new \phpbb\db\tools\factory(); +		$this->tools = $factory->get($this->db);  		$this->table_data = array(  			'COLUMNS'		=> array( @@ -340,7 +339,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case  	public function test_perform_schema_changes_drop_tables()  	{ -		$db_tools = $this->getMock('\phpbb\db\tools', array( +		$db_tools = $this->getMock('\phpbb\db\tools\tools', array(  			'sql_table_exists',  			'sql_table_drop',  		), array(&$this->db)); @@ -366,7 +365,7 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case  	public function test_perform_schema_changes_drop_columns()  	{ -		$db_tools = $this->getMock('\phpbb\db\tools', array( +		$db_tools = $this->getMock('\phpbb\db\tools\tools', array(  			'sql_column_exists',  			'sql_column_remove',  		), array(&$this->db)); diff --git a/tests/dbal/fixtures/boolean_processor.xml b/tests/dbal/fixtures/boolean_processor.xml new file mode 100644 index 0000000000..c5da677116 --- /dev/null +++ b/tests/dbal/fixtures/boolean_processor.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_banlist"> +		<column>ban_id</column> +		<column>ban_userid</column> +		<row> +			<value>1</value> +			<value>2</value> +		</row> +	</table> +	<table name="phpbb_users"> +		<column>user_id</column> +		<column>username</column> +		<column>username_clean</column> +		<column>user_permissions</column> +		<column>user_sig</column> +		<row> +			<value>1</value> +			<value>mass email</value> +			<value>mass email</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>2</value> +			<value>banned</value> +			<value>banned</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>3</value> +			<value>helper</value> +			<value>helper</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>4</value> +			<value>GroupBPal</value> +			<value>groupbpal</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>5</value> +			<value>GroupBPal2</value> +			<value>groupBPal2</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>6</value> +			<value>not in group</value> +			<value>not in group</value> +			<value></value> +			<value></value> +		</row> +	</table> +	<table name="phpbb_user_group"> +		<column>user_id</column> +		<column>group_id</column> +		<row> +			<value>1</value> +			<value>1</value> +		</row> +		<row> +			<value>2</value> +			<value>1</value> +		</row> +		<row> +			<value>3</value> +			<value>1</value> +		</row> +		<row> +			<value>4</value> +			<value>2</value> +		</row> +		<row> +			<value>5</value> +			<value>2</value> +		</row> +	</table> +</dataset> diff --git a/tests/dbal/migrator_test.php b/tests/dbal/migrator_test.php index 798200eef1..f7275a4bbe 100644 --- a/tests/dbal/migrator_test.php +++ b/tests/dbal/migrator_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/migration/dummy.php';  require_once dirname(__FILE__) . '/migration/unfulfillable.php';  require_once dirname(__FILE__) . '/migration/if.php'; @@ -38,7 +37,8 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case  		parent::setUp();  		$this->db = $this->new_dbal(); -		$this->db_tools = new \phpbb\db\tools($this->db); +		$factory = new \phpbb\db\tools\factory(); +		$this->db_tools = $factory->get($this->db);  		$this->config = new \phpbb\config\db($this->db, new phpbb_mock_cache, 'phpbb_config'); @@ -62,14 +62,12 @@ class phpbb_dbal_migrator_test extends phpbb_database_test_case  		);  		$container->set('migrator', $this->migrator);  		$container->set('dispatcher', new phpbb_mock_event_dispatcher()); -		$user = new \phpbb\user('\phpbb\datetime');  		$this->extension_manager = new \phpbb\extension\manager(  			$container,  			$this->db,  			$this->config, -			new phpbb\filesystem(), -			$user, +			new phpbb\filesystem\filesystem(),  			'phpbb_ext',  			dirname(__FILE__) . '/../../phpBB/',  			'php', diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php index bbe543f347..29b21166b6 100644 --- a/tests/dbal/migrator_tool_module_test.php +++ b/tests/dbal/migrator_tool_module_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -27,19 +25,24 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case  		parent::setup(); -		// Force add_log function to not be used +		// Disable the logs  		$skip_add_log = true;  		$db = $this->db = $this->new_dbal(); -		$this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); -		$user = $this->user = new \phpbb\user('\phpbb\user'); +		$this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = $this->user = new \phpbb\user($lang, '\phpbb\datetime');  		$cache = new phpbb_mock_cache;  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$auth = $this->getMock('\phpbb\auth\auth');  		$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); -		$this->tool = new \phpbb\db\migration\tool\module($this->db, $this->cache, $this->user, $phpbb_root_path, $phpEx, 'phpbb_modules'); +		$phpbb_extension_manager = new phpbb_mock_extension_manager($phpbb_root_path); +		$module_manager = new \phpbb\module\module_manager($cache, $this->db, $phpbb_extension_manager, MODULES_TABLE, $phpbb_root_path, $phpEx); + +		$this->tool = new \phpbb\db\migration\tool\module($this->db, $this->cache, $this->user, $module_manager, $phpbb_root_path, $phpEx, 'phpbb_modules');  	}  	public function exists_data_acp() diff --git a/tests/dbal/migrator_tool_permission_test.php b/tests/dbal/migrator_tool_permission_test.php index 2d673864f7..d84f6a68ff 100644 --- a/tests/dbal/migrator_tool_permission_test.php +++ b/tests/dbal/migrator_tool_permission_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_migrator_tool_permission_test extends phpbb_database_test_case  {  	public $group_ids = array( @@ -34,7 +32,7 @@ class phpbb_dbal_migrator_tool_permission_test extends phpbb_database_test_case  		parent::setup();  		$db = $this->db = $this->new_dbal(); -		$cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx); +		$cache = $this->cache = new \phpbb\cache\service(new \phpbb\cache\driver\dummy(), new \phpbb\config\config(array()), $this->db, $phpbb_root_path, $phpEx);  		$this->auth = new \phpbb\auth\auth();  		$this->tool = new \phpbb\db\migration\tool\permission($this->db, $this->cache, $this->auth, $phpbb_root_path, $phpEx); diff --git a/tests/dbal/schema_test.php b/tests/dbal/schema_test.php index f13c7ce032..59965655ad 100644 --- a/tests/dbal/schema_test.php +++ b/tests/dbal/schema_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_schema_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/dbal/select_test.php b/tests/dbal/select_test.php index b7074552ba..0dac66fc46 100644 --- a/tests/dbal/select_test.php +++ b/tests/dbal/select_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_dbal_select_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/dbal/write_sequence_test.php b/tests/dbal/write_sequence_test.php index a1b589c578..a2d5921797 100644 --- a/tests/dbal/write_sequence_test.php +++ b/tests/dbal/write_sequence_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_write_sequence_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/dbal/write_test.php b/tests/dbal/write_test.php index 2426f2b0be..98709fb043 100644 --- a/tests/dbal/write_test.php +++ b/tests/dbal/write_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_dbal_write_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/di/create_container_test.php b/tests/di/create_container_test.php index 4ae6017989..aba7a3560b 100644 --- a/tests/di/create_container_test.php +++ b/tests/di/create_container_test.php @@ -13,7 +13,7 @@  namespace  { -	require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +	require_once dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/di/extension.php';  	class phpbb_di_container_test extends \phpbb_test_case  	{ @@ -30,7 +30,8 @@ namespace  		{  			$this->phpbb_root_path = dirname(__FILE__) . '/';  			$this->config_php = new \phpbb\config_php_file($this->phpbb_root_path . 'fixtures/', 'php'); -			$this->builder = new phpbb_mock_phpbb_di_container_builder($this->config_php, $this->phpbb_root_path . 'fixtures/', 'php'); +			$this->builder = new phpbb_mock_phpbb_di_container_builder($this->phpbb_root_path . 'fixtures/', 'php'); +			$this->builder->with_config($this->config_php);  			$this->filename = $this->phpbb_root_path . '../tmp/container.php';  			if (is_file($this->filename)) @@ -57,6 +58,9 @@ namespace  			// Checks use_extensions  			$this->assertTrue($container->hasParameter('enabled')); +			$this->assertTrue($container->hasParameter('enabled_2')); +			$this->assertTrue($container->hasParameter('enabled_3')); +			$this->assertTrue($container->hasParameter('enabled_4'));  			$this->assertFalse($container->hasParameter('disabled'));  			$this->assertFalse($container->hasParameter('available')); @@ -69,14 +73,12 @@ namespace  			// Checks the construction of a dumped container  			$container = $this->builder->get_container();  			$this->assertInstanceOf('phpbb_cache_container', $container); -			$this->assertFalse($container->isFrozen()); -			$container->getParameterBag(); // needed, otherwise the container is not marked as frozen  			$this->assertTrue($container->isFrozen());  		} -		public function test_dump_container() +		public function test_without_cache()  		{ -			$this->builder->set_dump_container(false); +			$this->builder->without_cache();  			$container = $this->builder->get_container();  			$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -90,9 +92,9 @@ namespace  			$this->assertTrue($container->isFrozen());  		} -		public function test_use_extensions() +		public function test_without_extensions()  		{ -			$this->builder->set_use_extensions(false); +			$this->builder->without_extensions();  			$container = $this->builder->get_container();  			$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -105,9 +107,9 @@ namespace  			$this->assertFalse($container->hasParameter('available'));  		} -		public function test_compile_container() +		public function test_without_compiled_container()  		{ -			$this->builder->set_compile_container(false); +			$this->builder->without_compiled_container();  			$container = $this->builder->get_container();  			$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -115,19 +117,9 @@ namespace  			$this->assertFalse($container->isFrozen());  		} -		public function test_inject_config() -		{ -			$this->builder->set_inject_config(false); -			$container = $this->builder->get_container(); -			$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); - -			// Checks inject_config -			$this->assertFalse($container->hasParameter('dbal.dbhost')); -		} - -		public function test_set_config_path() +		public function test_with_config_path()  		{ -			$this->builder->set_config_path($this->phpbb_root_path . 'fixtures/other_config/'); +			$this->builder->with_config_path($this->phpbb_root_path . 'fixtures/other_config/');  			$container = $this->builder->get_container();  			$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container); @@ -135,70 +127,32 @@ namespace  			$this->assertFalse($container->hasParameter('core'));  		} -		public function test_set_custom_parameters() +		public function test_with_custom_parameters()  		{ -			$this->builder->set_custom_parameters(array('my_parameter' => true)); +			$this->builder->with_custom_parameters(array('my_parameter' => true));  			$container = $this->builder->get_container();  			$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerBuilder', $container);  			$this->assertTrue($container->hasParameter('my_parameter')); -			$this->assertFalse($container->hasParameter('core.root_path'));  		}  	}  } -namespace phpbb\db\driver +namespace phpbb\extension  { -	class container_mock extends \phpbb\db\driver\driver +	class manager_mock extends \phpbb\extension\manager  	{ -		public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) -		{ -		} - -		public function sql_query($query = '', $cache_ttl = 0) -		{ -		} - -		public function sql_fetchrow($query_id = false) -		{ -		} - -		public function sql_freeresult($query_id = false) -		{ -		} - -		function sql_server_info($raw = false, $use_cache = true) -		{ -		} - -		function sql_affectedrows() -		{ -		} - -		function sql_rowseek($rownum, &$query_id) -		{ -		} - -		function sql_nextid() -		{ -		} - -		function sql_escape($msg) -		{ -		} - -		function sql_like_expression($expression) -		{ -		} - -		function sql_not_like_expression($expression) +		public function __construct()  		{  		} -		function sql_fetchrowset($query_id = false) +		public function all_enabled($phpbb_relative = true)  		{  			return array( -				array('ext_name' => 'vendor/enabled'), +				'vendor/enabled' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled/', +				'vendor/enabled-2' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled-2/', +				'vendor/enabled-3' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled-3/', +				'vendor/enabled_4' => dirname(__FILE__) . '/fixtures/ext/vendor/enabled_4/',  			);  		}  	} diff --git a/tests/di/fixtures/config.php b/tests/di/fixtures/config.php index 04e20f63d8..1e9207d924 100644 --- a/tests/di/fixtures/config.php +++ b/tests/di/fixtures/config.php @@ -1,11 +1,11 @@  <?php  // phpBB 3.1.x auto-generated configuration file  // Do not change anything in this file! -$dbms = 'container_mock'; +$dbms = 'mysql';  $dbhost = '127.0.0.1';  $dbport = '';  $dbname = 'phpbb';  $dbuser = 'root';  $dbpasswd = '';  $table_prefix = 'phpbb_'; -$acm_type = '\phpbb\cache\driver\null'; +$acm_type = '\phpbb\cache\driver\dummy'; diff --git a/tests/di/fixtures/config/production/config.yml b/tests/di/fixtures/config/production/config.yml new file mode 100644 index 0000000000..fcfa84f68b --- /dev/null +++ b/tests/di/fixtures/config/production/config.yml @@ -0,0 +1,2 @@ +core: +    require_dev_dependencies: true diff --git a/tests/di/fixtures/config/production/container/environment.yml b/tests/di/fixtures/config/production/container/environment.yml new file mode 100644 index 0000000000..4216b187cc --- /dev/null +++ b/tests/di/fixtures/config/production/container/environment.yml @@ -0,0 +1,29 @@ +parameters: +    core: true + +services: +    config.php: +        synthetic: true + +    dbal.conn: +        class: phpbb\db\driver\factory +        arguments: +            - '@service_container' + +    dispatcher: +        class: phpbb\db\driver\container_mock + +    ext.manager: +        class: phpbb\extension\manager_mock + +    template.twig.environment: +        class: Exception +        arguments: +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - [] diff --git a/tests/di/fixtures/config/services.yml b/tests/di/fixtures/config/services.yml deleted file mode 100644 index f2a22ae109..0000000000 --- a/tests/di/fixtures/config/services.yml +++ /dev/null @@ -1,14 +0,0 @@ -parameters: -    core: true - -services: -    config.php: -        synthetic: true - -    dbal.conn: -        class: phpbb\db\driver\factory -        arguments: -            - @service_container - -    dispatcher: -        class: phpbb\db\driver\container_mock diff --git a/tests/di/fixtures/config/test/config.yml b/tests/di/fixtures/config/test/config.yml new file mode 100644 index 0000000000..fcfa84f68b --- /dev/null +++ b/tests/di/fixtures/config/test/config.yml @@ -0,0 +1,2 @@ +core: +    require_dev_dependencies: true diff --git a/tests/di/fixtures/config/test/container/environment.yml b/tests/di/fixtures/config/test/container/environment.yml new file mode 100644 index 0000000000..7d528fed19 --- /dev/null +++ b/tests/di/fixtures/config/test/container/environment.yml @@ -0,0 +1,26 @@ +parameters: +    core: true + +services: +    config.php: +        synthetic: true + +    dbal.conn: +        class: phpbb\db\driver\factory +        arguments: +            - '@service_container' + +    dispatcher: +        class: phpbb\db\driver\container_mock + +    template.twig.environment: +        class: Exception +        arguments: +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - [] diff --git a/tests/di/fixtures/ext/vendor/disabled/config/services.yml b/tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml index 31ada384bf..31ada384bf 100644 --- a/tests/di/fixtures/ext/vendor/disabled/config/services.yml +++ b/tests/di/fixtures/ext/vendor/disabled/config/test/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml b/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml new file mode 100644 index 0000000000..feeb5a7a2d --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled-2/config/test/container/environment.yml @@ -0,0 +1,2 @@ +parameters: +    enabled_2: true diff --git a/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml b/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml new file mode 100644 index 0000000000..0dae35d2bd --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled-3/config/services.yml @@ -0,0 +1,2 @@ +parameters: +    enabled_3: true diff --git a/tests/di/fixtures/ext/vendor/enabled/config/services.yml b/tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml index 88a7919ed1..88a7919ed1 100644 --- a/tests/di/fixtures/ext/vendor/enabled/config/services.yml +++ b/tests/di/fixtures/ext/vendor/enabled/config/default/container/environment.yml diff --git a/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php new file mode 100644 index 0000000000..8e5ed6c52c --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled_4/di/extension.php @@ -0,0 +1,32 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace vendor\enabled_4\di; + +use phpbb\extension\di\extension_base; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +/** +* Container core extension +*/ +class extension extends extension_base +{ +	protected function load_services(ContainerBuilder $container) +	{ +		$filesystem = new \phpbb\filesystem\filesystem(); +		$loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($this->ext_path))); +		$loader->load('environment.yml'); +	} +} diff --git a/tests/di/fixtures/ext/vendor/enabled_4/environment.yml b/tests/di/fixtures/ext/vendor/enabled_4/environment.yml new file mode 100644 index 0000000000..d0affe4fd6 --- /dev/null +++ b/tests/di/fixtures/ext/vendor/enabled_4/environment.yml @@ -0,0 +1,2 @@ +parameters: +    enabled_4: true diff --git a/tests/di/fixtures/other_config/production/config.yml b/tests/di/fixtures/other_config/production/config.yml new file mode 100644 index 0000000000..fcfa84f68b --- /dev/null +++ b/tests/di/fixtures/other_config/production/config.yml @@ -0,0 +1,2 @@ +core: +    require_dev_dependencies: true diff --git a/tests/di/fixtures/other_config/production/container/environment.yml b/tests/di/fixtures/other_config/production/container/environment.yml new file mode 100644 index 0000000000..1170145b66 --- /dev/null +++ b/tests/di/fixtures/other_config/production/container/environment.yml @@ -0,0 +1,29 @@ +parameters: +    other_config: true + +services: +    config.php: +        synthetic: true + +    dbal.conn: +        class: phpbb\db\driver\factory +        arguments: +            - '@service_container' + +    dispatcher: +        class: phpbb\db\driver\container_mock + +    ext.manager: +        class: phpbb\extension\manager_mock + +    template.twig.environment: +        class: Exception +        arguments: +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - [] diff --git a/tests/di/fixtures/other_config/services.yml b/tests/di/fixtures/other_config/services.yml deleted file mode 100644 index c299bfc648..0000000000 --- a/tests/di/fixtures/other_config/services.yml +++ /dev/null @@ -1,14 +0,0 @@ -parameters: -    other_config: true - -services: -    config.php: -        synthetic: true - -    dbal.conn: -        class: phpbb\db\driver\factory -        arguments: -            - @service_container - -    dispatcher: -        class: phpbb\db\driver\container_mock diff --git a/tests/di/fixtures/other_config/test/config.yml b/tests/di/fixtures/other_config/test/config.yml new file mode 100644 index 0000000000..fcfa84f68b --- /dev/null +++ b/tests/di/fixtures/other_config/test/config.yml @@ -0,0 +1,2 @@ +core: +    require_dev_dependencies: true diff --git a/tests/di/fixtures/other_config/test/container/environment.yml b/tests/di/fixtures/other_config/test/container/environment.yml new file mode 100644 index 0000000000..6c36977d4d --- /dev/null +++ b/tests/di/fixtures/other_config/test/container/environment.yml @@ -0,0 +1,26 @@ +parameters: +    other_config: true + +services: +    config.php: +        synthetic: true + +    dbal.conn: +        class: phpbb\db\driver\factory +        arguments: +            - '@service_container' + +    dispatcher: +        class: phpbb\db\driver\container_mock + +    template.twig.environment: +        class: Exception +        arguments: +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - ~ +            - [] diff --git a/tests/di/ordered_service_collection_test.php b/tests/di/ordered_service_collection_test.php new file mode 100644 index 0000000000..47e6d23744 --- /dev/null +++ b/tests/di/ordered_service_collection_test.php @@ -0,0 +1,51 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_ordered_service_collection_test extends \phpbb_test_case +{ +	/** +	 * @var \phpbb\di\ordered_service_collection +	 */ +	protected $service_collection; + +	public function setUp() +	{ +		$container = new phpbb_mock_container_builder(); +		$container->set('foo', new StdClass); +		$container->set('bar', new StdClass); +		$container->set('foobar', new StdClass); +		$container->set('barfoo', new StdClass); + +		$this->service_collection = new \phpbb\di\ordered_service_collection($container); +		$this->service_collection->add('foo', 7); +		$this->service_collection->add('bar', 3); +		$this->service_collection->add('barfoo', 5); +		$this->service_collection->add('foobar', 2); + +		parent::setUp(); +	} + +	public function test_service_collection() +	{ +		$service_names = array(); + +		// Test the iterator +		foreach ($this->service_collection as $name => $service) +		{ +			$service_names[] = $name; +			$this->assertInstanceOf('StdClass', $service); +		} + +		$this->assertSame(array('foobar', 'bar', 'barfoo', 'foo'), $service_names); +	} +} diff --git a/tests/di/service_collection_test.php b/tests/di/service_collection_test.php new file mode 100644 index 0000000000..5b51254a4a --- /dev/null +++ b/tests/di/service_collection_test.php @@ -0,0 +1,47 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_service_collection_test extends \phpbb_test_case +{ +	/** +	 * @var \phpbb\di\service_collection +	 */ +	protected $service_collection; + +	public function setUp() +	{ +		$container = new phpbb_mock_container_builder(); +		$container->set('foo', new StdClass); +		$container->set('bar', new StdClass); + +		$this->service_collection = new \phpbb\di\service_collection($container); +		$this->service_collection->add('foo'); +		$this->service_collection->add('bar'); + +		parent::setUp(); +	} + +	public function test_service_collection() +	{ +		$service_names = array(); + +		// Test the iterator +		foreach ($this->service_collection as $name => $service) +		{ +			$service_names[] = $name; +			$this->assertInstanceOf('StdClass', $service); +		} + +		$this->assertSame(array('foo', 'bar'), $service_names); +	} +} diff --git a/tests/download/http_byte_range_test.php b/tests/download/http_byte_range_test.php index f920299048..8975ec1799 100644 --- a/tests/download/http_byte_range_test.php +++ b/tests/download/http_byte_range_test.php @@ -45,24 +45,72 @@ class phpbb_download_http_byte_range_test extends phpbb_test_case  	public function parse_range_request_data()  	{  		return array( -			// Does not read until the end of file. +            // Valid request  			array(  				array('3-4'),  				10, -				false, +				array( +					'byte_pos_start'	=> 3, +					'byte_pos_end'		=> 4, +					'bytes_requested'	=> 2, +					'bytes_total'		=> 10, +				),  			), -			// Valid request, handle second range. +            // Get the beginning  			array( -				array('0-0', '120-125'), -				125, +				array('-5'), +				10,  				array( -					'byte_pos_start'	=> 120, -					'byte_pos_end'		=> 124, +					'byte_pos_start'	=> 0, +					'byte_pos_end'		=> 5, +					'bytes_requested'	=> 6, +					'bytes_total'		=> 10, +				), +			), + +            // Get the end +			array( +				array('5-'), +				10, +				array( +					'byte_pos_start'	=> 5, +					'byte_pos_end'		=> 9,  					'bytes_requested'	=> 5, +					'bytes_total'		=> 10, +				), +			), + +            // Overlong request +			array( +				array('3-20'), +				10, +				array( +					'byte_pos_start'	=> 3, +					'byte_pos_end'		=> 9, +					'bytes_requested'	=> 7, +					'bytes_total'		=> 10, +				), +			), + +			// Multiple, contiguous range +			array( +				array('10-20', '21-30'), +				125, +				array( +					'byte_pos_start'	=> 10, +					'byte_pos_end'		=> 30, +					'bytes_requested'	=> 21,  					'bytes_total'		=> 125,  				)  			), + +			// We don't do multiple, non-contiguous range +			array( +				array('0-0', '120-125'), +				125, +				false, +			),  		);  	}  } diff --git a/tests/email/email_parsing_test.php b/tests/email/email_parsing_test.php new file mode 100644 index 0000000000..351a38514f --- /dev/null +++ b/tests/email/email_parsing_test.php @@ -0,0 +1,149 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_email_parsing_test extends phpbb_test_case +{ +	/** @var \messenger */ +	protected $messenger; + +	/** @var \ReflectionProperty */ +	protected $reflection_template_property; + +	public function setUp() +	{ +		global $phpbb_container, $config, $phpbb_root_path, $phpEx, $request, $user; + +		$phpbb_container = new phpbb_mock_container_builder; + +		$config = new \phpbb\config\config(array( +			'board_email_sig'     => '-- Thanks, The Management', +			'sitename' 			=> 'yourdomain.com', +			'default_lang'		=> 'en', +		)); +		$phpbb_container->set('config', $config); + +		$request = new phpbb_mock_request; +		$symfony_request = new \phpbb\symfony_request( +			$request +		); +		$filesystem = new \phpbb\filesystem\filesystem(); +		$phpbb_path_helper = new \phpbb\path_helper( +			$symfony_request, +			$filesystem, +			$request, +			$phpbb_root_path, +			$phpEx +		); +		$phpbb_container->set('path_helper', $phpbb_path_helper); +		$phpbb_container->set('filesystem', $filesystem); + +		$cache_path = $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/twig'; +		$phpbb_container->setParameter('core.template.cache_path', $cache_path); + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$phpbb_container->set('user', $user); +		$extension_manager = new phpbb_mock_extension_manager( +			dirname(__FILE__) . '/', +			array( +				'vendor2/foo' => array( +					'ext_name' => 'vendor2/foo', +					'ext_active' => '1', +					'ext_path' => 'ext/vendor2/foo/', +				), +			) +		); +		$phpbb_container->set('ext.manager', $extension_manager); + +		$context = new \phpbb\template\context(); +		$twig_extension = new \phpbb\template\twig\extension($context, $lang); +		$phpbb_container->set('template.twig.extensions.phpbb', $twig_extension); + +		$twig_extensions_collection = new \phpbb\di\service_collection($phpbb_container); +		$twig_extensions_collection->add('template.twig.extensions.phpbb'); +		$phpbb_container->set('template.twig.extensions.collection', $twig_extensions_collection); + +		$twig = new \phpbb\template\twig\environment( +			$config, +			$filesystem, +			$phpbb_path_helper, +			$cache_path, +			null, +			new \phpbb\template\twig\loader($filesystem, ''), +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		); +		$twig->addExtension($twig_extension); +		$phpbb_container->set('template.twig.lexer', new \phpbb\template\twig\lexer($twig)); + +		if (!class_exists('messenger')) +		{ +			include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); +		} + +		$this->messenger = new \messenger(); + +		$reflection = new ReflectionObject($this->messenger); +		$this->reflection_template_property = $reflection->getProperty('template'); +		$this->reflection_template_property->setAccessible(true); +	} + +	public function email_parsing_data() +	{ +		return array( +			array('Author username', 'Any forum', 'The topic title', 'Dear user'), +			array('0', 'Any forum', 'The topic title', 'Dear user'), +		); +	} + +	/** +	 * @dataProvider email_parsing_data +	 */ +	public function test_email_parsing($author_name, $forum_name, $topic_title, $username) +	{ +		global $config, $phpEx, $user; + +		$this->messenger->set_addresses($user->data); + +		$this->messenger->assign_vars(array( +			'EMAIL_SIG'	=> str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])), +			'SITENAME'	=> htmlspecialchars_decode($config['sitename']), + +			'AUTHOR_NAME'				=> $author_name, +			'FORUM_NAME'				=> $forum_name, +			'TOPIC_TITLE'				=> $topic_title, +			'USERNAME'					=> $username, + +			'U_FORUM'					=> generate_board_url() . "/viewforum.{$phpEx}?f=1", +			'U_STOP_WATCHING_FORUM'		=> generate_board_url() . "/viewforum.{$phpEx}?uid=2&f=1&unwatch=forum", +		)); +		$this->messenger->template('newtopic_notify', $user->data['user_lang'], '', ''); + +		$reflection_template = $this->reflection_template_property->getValue($this->messenger); +		$msg = trim($reflection_template->assign_display('body')); + +		$this->assertContains($author_name, $msg); +		$this->assertContains($forum_name, $msg); +		$this->assertContains($topic_title, $msg); +		$this->assertContains($username, $msg); +		$this->assertContains(htmlspecialchars_decode($config['sitename']), $msg); +		$this->assertContains(str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])), $msg); +		$this->assertNotContains('EMAIL_SIG', $msg); +		$this->assertNotContains('U_STOP_WATCHING_FORUM', $msg); +	} +} diff --git a/tests/error_collector_test.php b/tests/error_collector_test.php index b92c4fa6bb..273284c8fc 100644 --- a/tests/error_collector_test.php +++ b/tests/error_collector_test.php @@ -11,10 +11,17 @@  *  */ -require_once dirname(__FILE__) . '/../phpBB/includes/functions.php'; -  class phpbb_error_collector_test extends phpbb_test_case  { +	public function setUp() +	{ +		parent::setUp(); + +		global $phpbb_filesystem; + +		$phpbb_filesystem = new \phpbb\filesystem\filesystem(); +	} +  	public function test_collection()  	{  		$collector = new \phpbb\error_collector(E_ALL | E_STRICT); // php set_error_handler() default diff --git a/tests/event/exception_listener_test.php b/tests/event/exception_listener_test.php index 4d3453cd83..08679a3ed8 100644 --- a/tests/event/exception_listener_test.php +++ b/tests/event/exception_listener_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class exception_listener extends phpbb_test_case  {  	public function phpbb_exception_data() @@ -79,10 +77,12 @@ class exception_listener extends phpbb_test_case  			->disableOriginalConstructor()  			->getMock(); -		$user = new \phpbb\user('\phpbb\datetime'); -		$user->add_lang('common'); +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); -		$exception_listener = new \phpbb\event\kernel_exception_subscriber($template, $user); +		$exception_listener = new \phpbb\event\kernel_exception_subscriber($template, $lang);  		$event = new \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, \Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST, $exception);  		$exception_listener->on_kernel_exception($event); diff --git a/tests/event/md_exporter_test.php b/tests/event/md_exporter_test.php index 1a51204cbe..607f442fdf 100644 --- a/tests/event/md_exporter_test.php +++ b/tests/event/md_exporter_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_event_md_exporter_test extends phpbb_test_case  {  	static public function crawl_eventsmd_data() @@ -23,7 +21,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case  					'event' => 'acp_bbcodes_actions_append',  					'files' => array(  						'prosilver' => array(), -						'subsilver2' => array(),  						'adm' => array('acp_bbcodes.html'),  					),  					'since' => '3.1.0-a3', @@ -36,7 +33,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case  					'event' => 'acp_bbcodes_actions_prepend',  					'files' => array(  						'prosilver' => array(), -						'subsilver2' => array(),  						'adm' => array('acp_bbcodes.html'),  					),  					'since' => '3.1.0-a5', @@ -47,7 +43,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case  					'event' => 'acp_bbcodes_actions_prepend2',  					'files' => array(  						'prosilver' => array(), -						'subsilver2' => array(),  						'adm' => array('acp_bbcodes.html'),  					),  					'since' => '3.1.0-a4', @@ -63,7 +58,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case  					'event' => 'acp_bbcodes_actions_prepend',  					'files' => array(  						'prosilver' => array(), -						'subsilver2' => array(),  						'adm' => array('acp_bbcodes.html'),  					),  					'since' => '3.1.0-a5', @@ -74,7 +68,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case  					'event' => 'acp_bbcodes_actions_prepend2',  					'files' => array(  						'prosilver' => array(), -						'subsilver2' => array(),  						'adm' => array('acp_bbcodes.html'),  					),  					'since' => '3.1.0-a4', @@ -130,7 +123,6 @@ class phpbb_event_md_exporter_test extends phpbb_test_case  		$styles = array(  			'adm/style/' => 'adm',  			'styles/prosilver/template/' => 'styles', -			'styles/subsilver2/template/' => 'styles',  		);  		foreach ($styles as $path => $filter)  		{ diff --git a/tests/extension/ext/vendor2/bar/acp/a_info.php b/tests/extension/ext/vendor2/bar/acp/a_info.php index 8132df587f..8268006f9f 100644 --- a/tests/extension/ext/vendor2/bar/acp/a_info.php +++ b/tests/extension/ext/vendor2/bar/acp/a_info.php @@ -9,7 +9,6 @@ class a_info  		return array(  			'filename'	=> 'vendor2\\bar\\acp\\a_module',  			'title'		=> 'Bar', -			'version'	=> '3.1.0-dev',  			'modes'		=> array(  				'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('ACP_MODS')),  			), diff --git a/tests/extension/ext/vendor2/bar/migrations/bar.php b/tests/extension/ext/vendor2/bar/migrations/bar.php new file mode 100644 index 0000000000..ea5ddb6b8b --- /dev/null +++ b/tests/extension/ext/vendor2/bar/migrations/bar.php @@ -0,0 +1,7 @@ +<?php + +namespace vendor2\foo\migrations; + +class bar +{ +} diff --git a/tests/extension/ext/vendor2/bar/migrations/foo.php b/tests/extension/ext/vendor2/bar/migrations/foo.php new file mode 100644 index 0000000000..d727c2f954 --- /dev/null +++ b/tests/extension/ext/vendor2/bar/migrations/foo.php @@ -0,0 +1,54 @@ +<?php + +namespace vendor2\foo\migrations; + +class foo implements \phpbb\db\migration\migration_interface +{ +	/** +	 * {@inheritdoc} +	 */ +	static public function depends_on() +	{ +		return array(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function effectively_installed() +	{ +		return false; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function update_schema() +	{ +		return array(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function revert_schema() +	{ +		return array(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function update_data() +	{ +		return array(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function revert_data() +	{ +		return array(); +	} +} diff --git a/tests/extension/ext/vendor2/foo/acp/a_info.php b/tests/extension/ext/vendor2/foo/acp/a_info.php index e1eaa340b7..48ab4cf8e7 100644 --- a/tests/extension/ext/vendor2/foo/acp/a_info.php +++ b/tests/extension/ext/vendor2/foo/acp/a_info.php @@ -9,7 +9,6 @@ class a_info  		return array(  			'filename'	=> 'vendor2\\foo\\acp\\a_module',  			'title'		=> 'Foobar', -			'version'	=> '3.1.0-dev',  			'modes'		=> array(  				'config'		=> array('title' => 'Config',	'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')),  			), diff --git a/tests/extension/ext/vendor2/foo/acp/fail_info.php b/tests/extension/ext/vendor2/foo/acp/fail_info.php index d9b4353957..78479fee70 100644 --- a/tests/extension/ext/vendor2/foo/acp/fail_info.php +++ b/tests/extension/ext/vendor2/foo/acp/fail_info.php @@ -13,7 +13,6 @@ class foo_info  		return array(  			'filename'	=> 'vendor2\foo\acp\fail_module',  			'title'		=> 'Foobar', -			'version'	=> '3.1.0-dev',  			'modes'		=> array(  				'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('ACP_MODS')),  			), diff --git a/tests/extension/ext/vendor2/foo/mcp/a_info.php b/tests/extension/ext/vendor2/foo/mcp/a_info.php index b5599fde65..2532e44b12 100644 --- a/tests/extension/ext/vendor2/foo/mcp/a_info.php +++ b/tests/extension/ext/vendor2/foo/mcp/a_info.php @@ -9,7 +9,6 @@ class a_info  		return array(  			'filename'	=> 'vendor2\\foo\\mcp\\a_module',  			'title'		=> 'Foobar', -			'version'	=> '3.1.0-dev',  			'modes'		=> array(  				'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('MCP_MAIN')),  			), diff --git a/tests/extension/extension_base_test.php b/tests/extension/extension_base_test.php index eee38186db..e0c2e6d549 100644 --- a/tests/extension/extension_base_test.php +++ b/tests/extension/extension_base_test.php @@ -10,7 +10,9 @@  * the docs/CREDITS.txt file.  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/ext/vendor2/bar/migrations/bar.php'; +require_once dirname(__FILE__) . '/ext/vendor2/bar/migrations/foo.php'; +require_once dirname(__FILE__) . '/ext/vendor2/bar/migrations/migration.php';  class phpbb_extension_extension_base_test extends phpbb_test_case  { @@ -61,9 +63,7 @@ class phpbb_extension_extension_base_test extends phpbb_test_case  		return array(  			array(  				'vendor2/bar', -				array( -					'\vendor2\bar\migrations\migration', -				), +				array('\vendor2\bar\migrations\migration'),  			),  		);  	} @@ -74,6 +74,8 @@ class phpbb_extension_extension_base_test extends phpbb_test_case  	public function test_suffix_get_classes($extension_name, $expected)  	{  		$extension = $this->extension_manager->get_extension($extension_name); -		$this->assertEquals($expected, self::$reflection_method_get_migration_file_list->invoke($extension)); +		$migration_classes = self::$reflection_method_get_migration_file_list->invoke($extension); +		sort($migration_classes); +		$this->assertEquals($expected, $migration_classes);  	}  } diff --git a/tests/extension/finder_test.php b/tests/extension/finder_test.php index 2116cc057b..71de2c2fc5 100644 --- a/tests/extension/finder_test.php +++ b/tests/extension/finder_test.php @@ -10,7 +10,6 @@  * the docs/CREDITS.txt file.  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_extension_finder_test extends phpbb_test_case  { @@ -244,7 +243,7 @@ class phpbb_extension_finder_test extends phpbb_test_case  	public function test_get_classes_create_cache()  	{  		$cache = new phpbb_mock_cache; -		$finder = new \phpbb\finder(new \phpbb\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name'); +		$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name');  		$finder->set_extensions(array_keys($this->extension_manager->all_enabled()));  		$files = $finder->suffix('_class.php')->get_files(); @@ -284,7 +283,7 @@ class phpbb_extension_finder_test extends phpbb_test_case  		);  		$finder = new \phpbb\finder( -			new \phpbb\filesystem(), +			new \phpbb\filesystem\filesystem(),  			dirname(__FILE__) . '/',  			new phpbb_mock_cache(array(  				'_ext_finder' => array( diff --git a/tests/extension/includes/acp/info/acp_foobar.php b/tests/extension/includes/acp/info/acp_foobar.php index 870225ba4f..8ca1afa1c6 100644 --- a/tests/extension/includes/acp/info/acp_foobar.php +++ b/tests/extension/includes/acp/info/acp_foobar.php @@ -18,7 +18,6 @@ class acp_foobar_info  		return array(  			'filename'	=> 'acp_foobar',  			'title'		=> 'ACP Foobar', -			'version'	=> '3.1.0-dev',  			'modes'		=> array(  				'test'		=> array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')),  			), diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php index 0eeb060936..a24b0cf178 100644 --- a/tests/extension/manager_test.php +++ b/tests/extension/manager_test.php @@ -150,11 +150,11 @@ class phpbb_extension_manager_test extends phpbb_database_test_case  		$config = new \phpbb\config\config(array('version' => PHPBB_VERSION));  		$db = $this->new_dbal(); -		$db_tools = new \phpbb\db\tools($db); +		$factory = new \phpbb\db\tools\factory(); +		$db_tools = $factory->get($db);  		$phpbb_root_path = __DIR__ . './../../phpBB/';  		$php_ext = 'php';  		$table_prefix = 'phpbb_'; -		$user = new \phpbb\user('\phpbb\user');  		$container = new phpbb_mock_container_builder(); @@ -176,8 +176,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case  			$container,  			$db,  			$config, -			new \phpbb\filesystem(), -			$user, +			new \phpbb\filesystem\filesystem(),  			'phpbb_ext',  			dirname(__FILE__) . '/',  			$php_ext, diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php index 2a746d3792..19b99ee0ce 100644 --- a/tests/extension/metadata_manager_test.php +++ b/tests/extension/metadata_manager_test.php @@ -41,25 +41,39 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  			'version'		=> '3.1.0',  		));  		$this->db = $this->new_dbal(); -		$this->db_tools = new \phpbb\db\tools($this->db); +		$factory = new \phpbb\db\tools\factory(); +		$this->db_tools = $factory->get($this->db);  		$this->phpbb_root_path = dirname(__FILE__) . '/';  		$this->phpEx = 'php'; -		$this->user = new \phpbb\user('\phpbb\datetime');  		$this->table_prefix = 'phpbb_'; -		$this->template = new \phpbb\template\twig\twig( -			new \phpbb\path_helper( -				new \phpbb\symfony_request( -					new phpbb_mock_request() -				), -				new \phpbb\filesystem(), -				$this->getMock('\phpbb\request\request'), -				$this->phpbb_root_path, -				$this->phpEx +		$container = new phpbb_mock_container_builder(); +		$cache_path = $this->phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); +		$filesystem = new \phpbb\filesystem\filesystem(); +		$phpbb_path_helper = new \phpbb\path_helper( +			new \phpbb\symfony_request( +				new phpbb_mock_request()  			), +			$filesystem, +			$this->getMock('\phpbb\request\request'), +			$this->phpbb_root_path, +			$this->phpEx +		); +		$twig = new \phpbb\template\twig\environment(  			$this->config, -			$this->user, -			new \phpbb\template\context() +			$filesystem, +			$phpbb_path_helper, +			$cache_path, +			null, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			)  		);  		$container = new phpbb_mock_container_builder(); @@ -82,13 +96,22 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  			$container,  			$this->db,  			$this->config, -			new \phpbb\filesystem(), -			$this->user, +			new \phpbb\filesystem\filesystem(),  			'phpbb_ext',  			$this->phpbb_root_path,  			$this->phpEx,  			$this->cache  		); + +		global $phpbb_root_path; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $this->phpEx); +		$lang_loader->set_extension_manager($this->extension_manager); +		$lang = new \phpbb\language\language($lang_loader); +		$this->user = new \phpbb\user($lang, '\phpbb\datetime'); + +		$this->template = new phpbb\template\twig\twig($phpbb_path_helper, $this->config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig));  	}  	// Should fail from missing composer.json @@ -104,7 +127,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  		}  		catch (\phpbb\extension\exception $e)  		{ -			$this->assertEquals((string) $e, $this->user->lang('FILE_NOT_FOUND', $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json')); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); +			$this->assertEquals($message, $this->user->lang('FILE_NOT_FOUND', $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json'));  		}  	} @@ -121,7 +145,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  		}  		catch (\phpbb\extension\exception $e)  		{ -			$this->fail($e); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); +			$this->fail($message);  		}  		$json = json_decode(file_get_contents($this->phpbb_root_path . 'ext/vendor2/foo/composer.json'), true); @@ -151,9 +176,10 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  			$manager->validate($field_name);  			$this->fail('Exception not triggered');  		} -		catch(\phpbb\extension\exception $e) +		catch (\phpbb\extension\exception $e)  		{ -			$this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', $field_name)); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); +			$this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', $field_name));  		}  	} @@ -167,7 +193,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  		}  		catch (\phpbb\extension\exception $e)  		{ -			$this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', 'authors')); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); +			$this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', 'authors'));  		}  		$manager->merge_metadata(array( @@ -183,7 +210,8 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  		}  		catch (\phpbb\extension\exception $e)  		{ -			$this->assertEquals((string) $e, $this->user->lang('META_FIELD_NOT_SET', 'author name')); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); +			$this->assertEquals($message, $this->user->lang('META_FIELD_NOT_SET', 'author name'));  		}  	} @@ -214,9 +242,10 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  			$manager->validate($field_name);  			$this->fail('Exception not triggered');  		} -		catch(\phpbb\extension\exception $e) +		catch (\phpbb\extension\exception $e)  		{ -			$this->assertEquals((string) $e, $this->user->lang('META_FIELD_INVALID', $field_name)); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); +			$this->assertEquals($message, $this->user->lang('META_FIELD_INVALID', $field_name));  		}  	} @@ -238,9 +267,9 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  		{  			$this->assertEquals(true, $manager->validate('enable'));  		} -		catch(\phpbb\extension\exception $e) +		catch (\phpbb\extension\exception $e)  		{ -			$this->fail($e); +			$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));  		}  	} @@ -336,7 +365,6 @@ class phpbb_extension_metadata_manager_test extends phpbb_database_test_case  			$this->config,  			$this->extension_manager,  			$this->template, -			$this->user,  			$this->phpbb_root_path  		);  	} diff --git a/tests/extension/modules_test.php b/tests/extension/modules_test.php index 21f1c6aca5..88634bc6ba 100644 --- a/tests/extension/modules_test.php +++ b/tests/extension/modules_test.php @@ -22,6 +22,7 @@ class phpbb_extension_modules_test extends phpbb_test_case  {  	protected $extension_manager;  	protected $finder; +	protected $module_manager;  	public function setUp()  	{ @@ -43,7 +44,14 @@ class phpbb_extension_modules_test extends phpbb_test_case  			));  		$phpbb_extension_manager = $this->extension_manager; -		$this->acp_modules = new acp_modules(); +		$this->module_manager = new \phpbb\module\module_manager( +			new \phpbb\cache\driver\dummy(), +			$this->getMock('\phpbb\db\driver\driver_interface'), +			$this->extension_manager, +			MODULES_TABLE, +			dirname(__FILE__) . '/', +			'php' +		);  	}  	public function test_get_module_infos() @@ -56,13 +64,11 @@ class phpbb_extension_modules_test extends phpbb_test_case  		$phpbb_root_path = dirname(__FILE__) . '/';  		// Find acp module info files -		$this->acp_modules->module_class = 'acp'; -		$acp_modules = $this->acp_modules->get_module_infos(); +		$acp_modules = $this->module_manager->get_module_infos('acp');  		$this->assertEquals(array(  				'vendor2\\foo\\acp\\a_module' => array(  					'filename'	=> 'vendor2\\foo\\acp\\a_module',  					'title'		=> 'Foobar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'config'		=> array('title' => 'Config',	'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')),  					), @@ -70,7 +76,6 @@ class phpbb_extension_modules_test extends phpbb_test_case  				'acp_foobar' => array(  					'filename'	=> 'acp_foobar',  					'title'		=> 'ACP Foobar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'test'		=> array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')),  					), @@ -78,13 +83,11 @@ class phpbb_extension_modules_test extends phpbb_test_case  			), $acp_modules);  		// Find mcp module info files -		$this->acp_modules->module_class = 'mcp'; -		$acp_modules = $this->acp_modules->get_module_infos(); +		$acp_modules = $this->module_manager->get_module_infos('mcp');  		$this->assertEquals(array(  				'vendor2\\foo\\mcp\\a_module' => array(  					'filename'	=> 'vendor2\\foo\\mcp\\a_module',  					'title'		=> 'Foobar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('MCP_MAIN')),  					), @@ -92,27 +95,11 @@ class phpbb_extension_modules_test extends phpbb_test_case  			), $acp_modules);  		// Find a specific module info file (mcp_a_module) -		$this->acp_modules->module_class = 'mcp'; -		$acp_modules = $this->acp_modules->get_module_infos('mcp_a_module'); -		$this->assertEquals(array( -				'vendor2\\foo\\mcp\\a_module' => array( -					'filename'	=> 'vendor2\\foo\\mcp\\a_module', -					'title'		=> 'Foobar', -					'version'	=> '3.1.0-dev', -					'modes'		=> array( -						'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('MCP_MAIN')), -					), -				), -			), $acp_modules); - -		// Find a specific module info file (mcp_a_module) with passing the module_class -		$this->acp_modules->module_class = ''; -		$acp_modules = $this->acp_modules->get_module_infos('mcp_a_module', 'mcp'); +		$acp_modules = $this->module_manager->get_module_infos('mcp', 'mcp_a_module');  		$this->assertEquals(array(  				'vendor2\\foo\\mcp\\a_module' => array(  					'filename'	=> 'vendor2\\foo\\mcp\\a_module',  					'title'		=> 'Foobar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('MCP_MAIN')),  					), @@ -120,23 +107,19 @@ class phpbb_extension_modules_test extends phpbb_test_case  			), $acp_modules);  		// The mcp module info file we're looking for shouldn't exist -		$this->acp_modules->module_class = 'mcp'; -		$acp_modules = $this->acp_modules->get_module_infos('mcp_a_fail'); +		$acp_modules = $this->module_manager->get_module_infos('mcp', 'mcp_a_fail');  		$this->assertEquals(array(), $acp_modules);  		// As there are no ucp modules we shouldn't find any -		$this->acp_modules->module_class = 'ucp'; -		$acp_modules = $this->acp_modules->get_module_infos(); +		$acp_modules = $this->module_manager->get_module_infos('ucp');  		$this->assertEquals(array(), $acp_modules);  		// Get module info of specified extension module -		$this->acp_modules->module_class = 'acp'; -		$acp_modules = $this->acp_modules->get_module_infos('foo_acp_a_module'); +		$acp_modules = $this->module_manager->get_module_infos('acp', 'foo_acp_a_module');  		$this->assertEquals(array(  				'vendor2\\foo\\acp\\a_module' => array (  					'filename' => 'vendor2\\foo\\acp\\a_module',  					'title' => 'Foobar', -					'version' => '3.1.0-dev',  					'modes' => array (  						'config'		=> array ('title' => 'Config', 'auth' => 'ext_vendor2/foo', 'cat' => array ('ACP_MODS')),  					), @@ -144,23 +127,20 @@ class phpbb_extension_modules_test extends phpbb_test_case  			), $acp_modules);  		// No specific module and module class set to an incorrect name -		$acp_modules = $this->acp_modules->get_module_infos('', 'wcp', true); +		$acp_modules = $this->module_manager->get_module_infos('wcp', '', true);  		$this->assertEquals(array(), $acp_modules);  		// No specific module, no module_class set in the function parameter, and an incorrect module class -		$this->acp_modules->module_class = 'wcp'; -		$acp_modules = $this->acp_modules->get_module_infos(); +		$acp_modules = $this->module_manager->get_module_infos('wcp');  		$this->assertEquals(array(), $acp_modules);  		// No specific module, module class set to false (will default to the above acp)  		// Setting $use_all_available will cause get_module_infos() to also load not enabled extensions (vendor2/bar) -		$this->acp_modules->module_class = 'acp'; -		$acp_modules = $this->acp_modules->get_module_infos('', false, true); +		$acp_modules = $this->module_manager->get_module_infos('acp', '', true);  		$this->assertEquals(array(  				'vendor2\\foo\\acp\\a_module' => array(  					'filename'	=> 'vendor2\\foo\\acp\\a_module',  					'title'		=> 'Foobar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'config'		=> array('title' => 'Config',	'auth' => 'ext_vendor2/foo', 'cat' => array('ACP_MODS')),  					), @@ -168,7 +148,6 @@ class phpbb_extension_modules_test extends phpbb_test_case  				'acp_foobar' => array(  					'filename'	=> 'acp_foobar',  					'title'		=> 'ACP Foobar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'test'		=> array('title' => 'Test', 'auth' => '', 'cat' => array('ACP_GENERAL')),  					), @@ -176,7 +155,6 @@ class phpbb_extension_modules_test extends phpbb_test_case  				'vendor2\\bar\\acp\\a_module' => array(  					'filename'	=> 'vendor2\\bar\\acp\\a_module',  					'title'		=> 'Bar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('ACP_MODS')),  					), @@ -184,12 +162,11 @@ class phpbb_extension_modules_test extends phpbb_test_case  			), $acp_modules);  		// Specific module set to disabled extension -		$acp_modules = $this->acp_modules->get_module_infos('vendor2_bar_acp_a_module', 'acp', true); +		$acp_modules = $this->module_manager->get_module_infos('acp', 'vendor2_bar_acp_a_module', true);  		$this->assertEquals(array(  				'vendor2\\bar\\acp\\a_module' => array(  					'filename'	=> 'vendor2\\bar\\acp\\a_module',  					'title'		=> 'Bar', -					'version'	=> '3.1.0-dev',  					'modes'		=> array(  						'config'		=> array('title' => 'Config',	'auth' => '', 'cat' => array('ACP_MODS')),  					), diff --git a/tests/files/type_foo.php b/tests/files/type_foo.php new file mode 100644 index 0000000000..95940b9d2f --- /dev/null +++ b/tests/files/type_foo.php @@ -0,0 +1,31 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\files\types; + +class foo extends \phpbb\files\types\remote +{ +	static public $tempnam_path; +} + +function tempnam($one, $two) +{ +	if (empty(foo::$tempnam_path)) +	{ +		return \tempnam($one, $two); +	} +	else +	{ +		return foo::$tempnam_path; +	} +} diff --git a/tests/files/types_base_test.php b/tests/files/types_base_test.php new file mode 100644 index 0000000000..e630bf8c48 --- /dev/null +++ b/tests/files/types_base_test.php @@ -0,0 +1,93 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_files_types_base_test extends phpbb_test_case +{ +	private $path; + +	private $filesystem; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	protected function setUp() +	{ +		global $phpbb_root_path, $phpEx; + +		$this->request = $this->getMock('\phpbb\request\request'); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->factory = new \phpbb\files\factory($this->container); + +		$this->path = __DIR__ . '/fixture/'; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function data_check_upload_size() +	{ +		return array( +			array('foo', '500KB', array()), +			array('none', '500KB', array('PHP_SIZE_OVERRUN')), +			array('none', '', array('PHP_SIZE_NA')), +		); +	} + +	/** +	 * @dataProvider data_check_upload_size +	 */ +	public function test_check_upload_size($filename, $max_filesize, $expected) +	{ +		$php_ini = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper'); +		$php_ini->expects($this->any()) +			->method('getString') +			->willReturn($max_filesize); +		$type_form = new \phpbb\files\types\local($this->factory, $this->language, $php_ini, $this->request); +		$file = $this->getMockBuilder('\phpbb\files\filespec') +			->disableOriginalConstructor() +			->getMock(); +		$file->expects($this->any()) +			->method('get') +			->willReturn($filename); +		$type_form->check_upload_size($file); + +		$this->assertSame($expected, $file->error); +	} +} diff --git a/tests/files/types_form_test.php b/tests/files/types_form_test.php new file mode 100644 index 0000000000..925babb47f --- /dev/null +++ b/tests/files/types_form_test.php @@ -0,0 +1,172 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_files_types_form_test extends phpbb_test_case +{ +	private $path; + +	private $filesystem; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var \phpbb\plupload\plupload */ +	protected $plupload; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	protected function setUp() +	{ +		global $phpbb_root_path, $phpEx; + +		$this->request = $this->getMock('\phpbb\request\request'); +		$this->request->expects($this->any()) +			->method('file') +			->willReturn(array()); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->factory = new \phpbb\files\factory($this->container); +		$this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload') +			->disableOriginalConstructor() +			->getMock(); +		$this->plupload->expects($this->any()) +			->method('handle_upload') +			->willReturn(array()); + +		$this->path = __DIR__ . '/fixture/'; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function data_upload_form() +	{ +		return array( +			array( +				array(), +				array(''), +			), +			array( +				array( +					'tmp_name'		=> 'foo', +					'name'			=> 'foo', +					'size'			=> 500, +					'type'			=> 'image/png', +					'error'			=> UPLOAD_ERR_PARTIAL, +				), +				array('PARTIAL_UPLOAD'), +			), +			array( +				array( +					'tmp_name'		=> 'foo', +					'name'			=> 'foo', +					'size'			=> 500, +					'type'			=> 'image/png', +					'error'			=> -9, +				), +				array('NOT_UPLOADED'), +			), +			array( +				array( +					'tmp_name'		=> 'foo', +					'name'			=> 'foo', +					'size'			=> 0, +					'type'			=> 'image/png', +				), +				array('EMPTY_FILEUPLOAD'), +			), +			array( +				array( +					'tmp_name'		=> 'none', +					'name'			=> 'none', +					'size'			=> 50, +					'type'			=> 'image/png', +				), +				array('PHP_SIZE_OVERRUN'), +			), +			array( +				array( +					'tmp_name'		=> 'tests/upload/fixture/png', +					'name'			=> 'foo.png', +					'size'			=> 500, +					'type'			=> 'image/png', +					'local_mode'	=> true, +				), +				array(), +				array('local_mode' => true), +			), +		); +	} + +	/** +	 * @dataProvider data_upload_form +	 */ +	public function test_upload_form($upload, $expected, $plupload = array()) +	{ +		$this->request = $this->getMock('\phpbb\request\request'); +		$this->request->expects($this->any()) +			->method('file') +			->willReturn($upload); +		$filespec = new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$this->phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			))); +		$this->container->set('files.filespec', $filespec); +		$this->factory = new \phpbb\files\factory($this->container); +		$this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload') +			->disableOriginalConstructor() +			->getMock(); +		$this->plupload->expects($this->any()) +			->method('handle_upload') +			->willReturn($plupload); + +		$type_form = new \phpbb\files\types\form($this->factory, $this->language, $this->php_ini, $this->plupload, $this->request); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('png')); +		$type_form->set_upload($upload); + + +		$file = $type_form->upload('foobar'); +		$this->assertSame($expected, $file->error); +		$this->assertInstanceOf('\phpbb\files\filespec', $file); +	} +} diff --git a/tests/files/types_local_test.php b/tests/files/types_local_test.php new file mode 100644 index 0000000000..31070de107 --- /dev/null +++ b/tests/files/types_local_test.php @@ -0,0 +1,161 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_files_types_local_test extends phpbb_test_case +{ +	private $path; + +	private $filesystem; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var \phpbb\plupload\plupload */ +	protected $plupload; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	protected function setUp() +	{ +		global $phpbb_root_path, $phpEx; + +		$this->request = $this->getMock('\phpbb\request\request'); +		$this->request->expects($this->any()) +			->method('file') +			->willReturn(array()); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->factory = new \phpbb\files\factory($this->container); +		$this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload') +			->disableOriginalConstructor() +			->getMock(); +		$this->plupload->expects($this->any()) +			->method('handle_upload') +			->willReturn(array()); + +		$this->path = __DIR__ . '/fixture/'; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function test_upload_init_error() +	{ +		$filespec = $this->getMockBuilder('\phpbb\files\filespec') +			->disableOriginalConstructor() +			->getMock(); +		$filespec->expects($this->any()) +			->method('init_error') +			->willReturn(true); +		$filespec->expects($this->any()) +			->method('set_upload_ary') +			->willReturnSelf(); +		$filespec->expects($this->any()) +			->method('set_upload_namespace') +			->willReturnSelf(); +		$this->container->set('files.filespec', $filespec); +		$this->factory = new \phpbb\files\factory($this->container); + +		$type_local = new \phpbb\files\types\local($this->factory, $this->language, $this->php_ini, $this->request); + + +		$file = $type_local->upload('foo', false); +		$this->assertSame(array(''), $file->error); +		$this->assertInstanceOf('\phpbb\files\filespec', $file); +	} + +	public function data_upload_form() +	{ +		return array( +			array( +				'foo', +				array( +					'tmp_name'		=> 'foo', +					'size'			=> 500, +					'type'			=> 'image/png', +				), +				array('NOT_UPLOADED'), +			), +			array( +				'none', +				false, +				array('PHP_SIZE_OVERRUN'), +			), +			array( +				'tests/upload/fixture/png', +				array( +					'realname'			=> 'foo.png', +					'size'			=> 500, +					'type'			=> 'image/png', +					'local_mode'	=> true, +				), +				array(), +			), +		); +	} + +	/** +	 * @dataProvider data_upload_form +	 */ +	public function test_upload_form($filename, $upload_ary, $expected) +	{ +		$filespec = new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$this->phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			))); +		$filespec_local = new ReflectionProperty($filespec, 'local'); +		$filespec_local->setAccessible(true); +		$filespec_local->setValue($filespec, true); +		$this->container->set('files.filespec', $filespec); +		$this->factory = new \phpbb\files\factory($this->container); + +		$type_local = new \phpbb\files\types\local($this->factory, $this->language, $this->php_ini, $this->request); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('png')); +		$type_local->set_upload($upload); + + +		$file = $type_local->upload($filename, $upload_ary); +		$this->assertSame($expected, $file->error); +		$this->assertInstanceOf('\phpbb\files\filespec', $file); +	} +} diff --git a/tests/files/types_remote_test.php b/tests/files/types_remote_test.php new file mode 100644 index 0000000000..d103771c04 --- /dev/null +++ b/tests/files/types_remote_test.php @@ -0,0 +1,132 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +require_once dirname(__FILE__) . '/type_foo.php'; + +class phpbb_files_types_remote_test extends phpbb_test_case +{ +	private $path; + +	private $filesystem; + +	/** @var \phpbb\config\config */ +	protected $config; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	protected function setUp() +	{ +		global $config, $phpbb_root_path, $phpEx; + +		$config = new \phpbb\config\config(array()); +		$this->config = $config; +		$this->config->set('remote_upload_verify', 0); +		$this->request = $this->getMock('\phpbb\request\request'); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->factory = new \phpbb\files\factory($this->container); + +		$this->path = __DIR__ . '/fixture/'; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function test_upload_fsock_fail() +	{ +		$type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('png')); +		$type_remote->set_upload($upload); + +		$file = $type_remote->upload('https://bärföö.com/foo.png'); + +		$this->assertSame(array('NOT_UPLOADED'), $file->error); +	} + +	public function data_get_max_file_size() +	{ +		return array( +			array('', 'http://example.com/foo/bar.png'), +			array('2k', 'http://example.com/foo/bar.png'), +			array('500k', 'http://example.com/foo/bar.png'), +			array('500M', 'http://example.com/foo/bar.png'), +			array('500m', 'http://example.com/foo/bar.png'), +			array('500k', 'http://google.com/?.png', array('DISALLOWED_EXTENSION', 'DISALLOWED_CONTENT')), +			array('1', 'http://google.com/?.png', array('WRONG_FILESIZE')), +			array('500g', 'http://example.com/foo/bar.png'), +			array('foobar', 'http://example.com/foo/bar.png'), +			array('-5k', 'http://example.com/foo/bar.png'), +		); +	} + +	/** +	 * @dataProvider data_get_max_file_size +	 */ +	public function test_get_max_file_size($max_file_size, $link, $expected = array('URL_NOT_FOUND')) +	{ +		$php_ini = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper', array('getString')); +		$php_ini->expects($this->any()) +			->method('getString') +			->willReturn($max_file_size); +		$type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->language, $php_ini, $this->request, $this->phpbb_root_path); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('png')); +		$type_remote->set_upload($upload); + +		$file = $type_remote->upload($link); + +		$this->assertSame($expected, $file->error); +	} + +	public function test_upload_wrong_path() +	{ +		$type_remote = new \phpbb\files\types\foo($this->config, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('png')); +		$type_remote->set_upload($upload); +		$type_remote::$tempnam_path = $this->phpbb_root_path . 'cache/wrong/path'; + +		$file = $type_remote->upload('http://google.com/?.png'); + +		$this->assertSame(array('NOT_UPLOADED'), $file->error); +		$type_remote::$tempnam_path = ''; +	} +} diff --git a/tests/files/upload_test.php b/tests/files/upload_test.php new file mode 100644 index 0000000000..c41204a0d5 --- /dev/null +++ b/tests/files/upload_test.php @@ -0,0 +1,128 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_files_upload_test extends phpbb_test_case +{ +	private $path; + +	private $filesystem; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; + +	protected function setUp() +	{ +		// Global $config required by unique_id +		global $config, $phpbb_root_path, $phpEx; + +		if (!is_array($config)) +		{ +			$config = array(); +		} + +		$config['rand_seed'] = ''; +		$config['rand_seed_last_update'] = time() + 600; + +		$this->request = $this->getMock('\phpbb\request\request'); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->factory = new \phpbb\files\factory($this->container); + +		$this->path = __DIR__ . '/fixture/'; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function test_reset_vars() +	{ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_max_filesize(500); +		$this->assertEquals(500, $upload->max_filesize); +		$upload->reset_vars(); +		$this->assertEquals(0, $upload->max_filesize); +	} + +	public function test_set_disallowed_content() +	{ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$disallowed_content = new ReflectionProperty($upload, 'disallowed_content'); +		$disallowed_content->setAccessible(true); + +		$upload->set_disallowed_content(array('foo')); +		$this->assertEquals(array('foo'), $disallowed_content->getValue($upload)); +		$upload->set_disallowed_content(array('foo', 'bar', 'meh')); +		$this->assertEquals(array('foo', 'bar', 'meh'), $disallowed_content->getValue($upload)); +		$upload->set_disallowed_content(''); +		$this->assertEquals(array('foo', 'bar', 'meh'), $disallowed_content->getValue($upload)); +		$this->assertINstanceOf('\phpbb\files\upload', $upload->set_disallowed_content(array())); +		$this->assertEquals(array(), $disallowed_content->getValue($upload)); +		$upload->reset_vars(); +		$this->assertEquals(array(), $disallowed_content->getValue($upload)); +	} + +	public function test_is_valid() +	{ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$this->assertFalse($upload->is_valid('foobar')); +	} + +	public function data_internal_error() +	{ +		return array( +			array(UPLOAD_ERR_INI_SIZE, 'PHP_SIZE_OVERRUN'), +			array(UPLOAD_ERR_FORM_SIZE, 'WRONG_FILESIZE'), +			array(UPLOAD_ERR_PARTIAL, 'PARTIAL_UPLOAD'), +			array(UPLOAD_ERR_NO_FILE, 'NOT_UPLOADED'), +			array(UPLOAD_ERR_NO_TMP_DIR, 'NO_TEMP_DIR'), +			array(UPLOAD_ERR_CANT_WRITE, 'NO_TEMP_DIR'), +			array(UPLOAD_ERR_EXTENSION, 'PHP_UPLOAD_STOPPED'), +			array(9, false), +		); +	} + +	/** +	 * @dataProvider data_internal_error +	 */ +	public function test_assign_internal_error($error_code, $expected) +	{ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$this->assertSame($expected, $upload->assign_internal_error($error_code)); +	} +} diff --git a/tests/filesystem/clean_path_test.php b/tests/filesystem/clean_path_test.php index c585b17155..d2dec424b4 100644 --- a/tests/filesystem/clean_path_test.php +++ b/tests/filesystem/clean_path_test.php @@ -18,7 +18,7 @@ class phpbb_filesystem_clean_path_test extends phpbb_test_case  	public function setUp()  	{  		parent::setUp(); -		$this->filesystem = new \phpbb\filesystem(); +		$this->filesystem = new \phpbb\filesystem\filesystem();  	}  	public function clean_path_data() diff --git a/tests/functions/is_absolute_test.php b/tests/filesystem/is_absolute_test.php index afa4b9b59f..7a50989b74 100644 --- a/tests/functions/is_absolute_test.php +++ b/tests/filesystem/is_absolute_test.php @@ -1,20 +1,28 @@  <?php  /** -* -* This file is part of the phpBB Forum Software package. -* -* @copyright (c) phpBB Limited <https://www.phpbb.com> -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; - -class phpbb_functions_is_absolute_test extends phpbb_test_case + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_filesystem_is_absolute_test extends phpbb_test_case  { +	/** @var \phpbb\filesystem\filesystem_interface */ +	protected $filesystem; + +	public function setUp() +	{ +		parent::setUp(); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +	} +  	static public function is_absolute_data()  	{  		return array( @@ -51,10 +59,10 @@ class phpbb_functions_is_absolute_test extends phpbb_test_case  	}  	/** -	* @dataProvider is_absolute_data -	*/ +	 * @dataProvider is_absolute_data +	 */  	public function test_is_absolute($path, $expected)  	{ -		$this->assertEquals($expected, phpbb_is_absolute($path)); +		$this->assertEquals($expected, $this->filesystem->is_absolute_path($path));  	}  } diff --git a/tests/filesystem/realpath_test.php b/tests/filesystem/realpath_test.php new file mode 100644 index 0000000000..d994935f94 --- /dev/null +++ b/tests/filesystem/realpath_test.php @@ -0,0 +1,90 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_filesystem_realpath_test extends phpbb_test_case +{ +	static protected $filesystem_own_realpath; + +	/** @var \phpbb\filesystem\filesystem_interface */ +	protected $filesystem; + +	static public function setUpBeforeClass() +	{ +		parent::setUpBeforeClass(); + +		$reflection_class = new ReflectionClass('\phpbb\filesystem\filesystem'); +		self::$filesystem_own_realpath = $reflection_class->getMethod('phpbb_own_realpath'); +		self::$filesystem_own_realpath->setAccessible(true); +	} + +	public function setUp() +	{ +		parent::setUp(); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +	} + +	public function realpath_resolve_absolute_without_symlinks_data() +	{ +		return array( +			// Constant data +			array(__DIR__, __DIR__), +			array(__DIR__ . '/../filesystem/../filesystem', __DIR__), +			array(__DIR__ . '/././', __DIR__), +			array(__DIR__ . '/non_existent', false), + +			array(__FILE__, __FILE__), +			array(__FILE__ . '../', false), +		); +	} + +	public function realpath_resolve_relative_without_symlinks_data() +	{ +		if (!function_exists('getcwd')) +		{ +			return array(); +		} + +		$filesystem = new \phpbb\filesystem\filesystem(); +		$relative_path = $filesystem->make_path_relative(__DIR__, getcwd()); + +		return array( +			array($relative_path, __DIR__), +			array($relative_path . '../filesystem/../filesystem', __DIR__), +			array($relative_path . '././', __DIR__), + +			array($relative_path . 'realpath_test.php', __FILE__), +		); +	} + +	/** +	 * @dataProvider realpath_resolve_absolute_without_symlinks_data +	 */ +	public function test_realpath_absolute_without_links($path, $expected) +	{ +		$this->assertEquals($expected, self::$filesystem_own_realpath->invoke($this->filesystem, $path)); +	} + +	/** +	 * @dataProvider realpath_resolve_relative_without_symlinks_data +	 */ +	public function test_realpath_relative_without_links($path, $expected) +	{ +		if (!function_exists('getcwd')) +		{ +			$this->markTestSkipped('phpbb_own_realpath() cannot be tested with relative paths: getcwd is not available.'); +		} + +		$this->assertEquals($expected, self::$filesystem_own_realpath->invoke($this->filesystem, $path)); +	} +} diff --git a/tests/functional/browse_test.php b/tests/functional/browse_test.php index b9e74a280f..280e814c06 100644 --- a/tests/functional/browse_test.php +++ b/tests/functional/browse_test.php @@ -34,9 +34,21 @@ class phpbb_functional_browse_test extends phpbb_functional_test_case  		$this->assertGreaterThan(0, $crawler->filter('.postbody')->count());  	} +	public function test_help_faq() +	{ +		$crawler = self::request('GET', 'app.php/help/faq'); +		$this->assertGreaterThan(0, $crawler->filter('h2.faq-title')->count()); +	} + +	public function test_help_bbcode() +	{ +		$crawler = self::request('GET', 'app.php/help/bbcode'); +		$this->assertGreaterThan(0, $crawler->filter('h2.faq-title')->count()); +	} +  	public function test_feed()  	{ -		$crawler = self::request('GET', 'feed.php', array(), false); +		$crawler = self::request('GET', 'app.php/feed', array(), false);  		self::assert_response_xml();  		$this->assertGreaterThan(0, $crawler->filter('entry')->count());  	} diff --git a/tests/functional/controllers_compatibility_test.php b/tests/functional/controllers_compatibility_test.php new file mode 100644 index 0000000000..9499888a1a --- /dev/null +++ b/tests/functional/controllers_compatibility_test.php @@ -0,0 +1,56 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group functional +*/ + +class phpbb_functional_controllers_compatibility_test extends phpbb_functional_test_case +{ +	public function test_report_compatibility() +	{ +		$this->assert301('report.php?f=1&p=1', 'app.php/post/1/report'); +		$this->assert301('report.php?p=1', 'app.php/post/1/report'); +		$this->assert301('report.php?pm=1', 'app.php/pm/1/report'); +	} + +	public function test_feed_compatibility() +	{ +		$this->assert301('feed.php', 'app.php/feed'); +		$this->assert301('feed.php?mode=foobar', 'app.php/feed/foobar'); +		$this->assert301('feed.php?mode=news', 'app.php/feed/news'); +		$this->assert301('feed.php?mode=topics', 'app.php/feed/topics'); +		$this->assert301('feed.php?mode=topics_news', 'app.php/feed/topics_news'); +		$this->assert301('feed.php?mode=topics_active', 'app.php/feed/topics_active'); +		$this->assert301('feed.php?mode=forums', 'app.php/feed/forums'); +		$this->assert301('feed.php?f=1', 'app.php/feed/forum/1'); +		$this->assert301('feed.php?t=1', 'app.php/feed/topic/1'); +	} + +	protected function assert301($from, $to) +	{ +		self::$client->followRedirects(false); +		self::request('GET', $from, array(), false); + +		// Fix sid issues +		$location = self::$client->getResponse()->getHeader('Location'); +		$location = preg_replace('#sid=[^&]+(&(amp;)?)?#', '', $location); +		if (substr($location, -1) === '?') +		{ +			$location = substr($location, 0, -1); +		} + +		$this->assertEquals(301, self::$client->getResponse()->getStatus()); +		$this->assertStringEndsWith($to, $location); +	} +} diff --git a/tests/functional/download_test.php b/tests/functional/download_test.php index 1e863210e6..e2f1d065be 100644 --- a/tests/functional/download_test.php +++ b/tests/functional/download_test.php @@ -11,10 +11,7 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  /**  * @group functional diff --git a/tests/functional/extension_module_test.php b/tests/functional/extension_module_test.php index ee084720e4..95107665cd 100644 --- a/tests/functional/extension_module_test.php +++ b/tests/functional/extension_module_test.php @@ -49,8 +49,9 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case  		$this->phpbb_extension_manager = $this->get_extension_manager();  		$this->phpbb_extension_manager->enable('foo/bar'); -		$modules = new acp_modules();  		$db = $this->get_db(); +		$cache = $this->get_cache_driver(); +		$modules = new \phpbb\module\module_manager($cache, $db, $this->phpbb_extension_manager, MODULES_TABLE, dirname(__FILE__) . '/../../phpBB/', 'php');  		$sql = 'SELECT module_id  			FROM ' . MODULES_TABLE . " @@ -70,7 +71,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case  			'module_mode'		=> '',  			'module_auth'		=> '',  		); -		$modules->update_module_data($parent_data, true); +		$modules->update_module_data($parent_data);  		$module_data = array(  			'module_basename'	=> 'foo\\bar\\acp\\main_module', @@ -82,7 +83,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case  			'module_mode'		=> 'mode',  			'module_auth'		=> '',  		); -		$modules->update_module_data($module_data, true); +		$modules->update_module_data($module_data);  		$parent_data = array(  			'module_basename'	=> '', @@ -94,7 +95,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case  			'module_mode'		=> '',  			'module_auth'		=> '',  		); -		$modules->update_module_data($parent_data, true); +		$modules->update_module_data($parent_data);  		$module_data = array(  			'module_basename'	=> 'foo\\bar\\ucp\\main_module', @@ -106,7 +107,7 @@ class phpbb_functional_extension_module_test extends phpbb_functional_test_case  			'module_mode'		=> 'mode',  			'module_auth'		=> '',  		); -		$modules->update_module_data($module_data, true); +		$modules->update_module_data($module_data);  		$this->purge_cache();  	} diff --git a/tests/functional/feed_test.php b/tests/functional/feed_test.php index e48dfc043a..3792b0a23c 100644 --- a/tests/functional/feed_test.php +++ b/tests/functional/feed_test.php @@ -30,9 +30,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  	{  		parent::__construct($name, $data, $dataName); -		$this->backupStaticAttributesBlacklist += array( -			'phpbb_functional_feed_test' => array('init_values'), -		); +		$this->backupStaticAttributesBlacklist['phpbb_functional_feed_test'] = array('init_values'); + +		$this->purge_cache();  	}  	public function test_setup_config_before_state() @@ -61,66 +61,64 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form->setValues($values);  		$crawler = self::submit($form); -		$this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text()); +		self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());  		// Special config (Guest can't see attachments)  		$this->add_lang('acp/permissions');  		$crawler = self::request('GET', "adm/index.php?i=acp_permissions&sid={$this->sid}&icat=16&mode=setting_group_global&group_id[0]=1"); -		$this->assertContains($this->lang('ACL_SET'), $crawler->filter('h1')->eq(1)->text()); +		self::assertContains($this->lang('ACL_SET'), $crawler->filter('h1')->eq(1)->text());  		$form = $crawler->selectButton($this->lang('APPLY_PERMISSIONS'))->form();  		$form['setting[1][0][u_download]']->select(-1);  		$crawler = self::submit($form); -		$this->assertContainsLang('AUTH_UPDATED', $crawler->filter('.successbox')->text()); +		self::assertContainsLang('AUTH_UPDATED', $crawler->filter('.successbox')->text());  	}  	public function test_dump_board_state()  	{ -		$crawler = self::request('GET', 'feed.php?mode=forums', array(), false); +		$crawler = self::request('GET', 'app.php/feed/forums', array(), false);  		self::assert_response_xml();  		self::$init_values['disapprove_user']['forums_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=overall', array(), false); +		$crawler = self::request('GET', 'app.php/feed/overall', array(), false);  		self::assert_response_xml();  		self::$init_values['disapprove_user']['overall_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=topics', array(), false); +		$crawler = self::request('GET', 'app.php/feed/topics', array(), false);  		self::assert_response_xml();  		self::$init_values['disapprove_user']['topics_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=topics_new', array(), false); +		$crawler = self::request('GET', 'app.php/feed/topics_new', array(), false);  		self::assert_response_xml();  		self::$init_values['disapprove_user']['topics_new_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=topics_active', array(), false); +		$crawler = self::request('GET', 'app.php/feed/topics_active', array(), false);  		self::assert_response_xml();  		self::$init_values['disapprove_user']['topics_active_value'] = $crawler->filterXPath('//entry')->count();  		$this->login(); -		$crawler = self::request('GET', 'feed.php?mode=forums', array(), false); +		$crawler = self::request('GET', 'app.php/feed/forums', array(), false);  		self::assert_response_xml();  		self::$init_values['admin']['forums_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=overall', array(), false); +		$crawler = self::request('GET', 'app.php/feed/overall', array(), false);  		self::assert_response_xml();  		self::$init_values['admin']['overall_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=topics', array(), false); +		$crawler = self::request('GET', 'app.php/feed/topics', array(), false);  		self::assert_response_xml();  		self::$init_values['admin']['topics_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=topics_new', array(), false); +		$crawler = self::request('GET', 'app.php/feed/topics_new', array(), false);  		self::assert_response_xml();  		self::$init_values['admin']['topics_new_value'] = $crawler->filterXPath('//entry')->count(); -		$crawler = self::request('GET', 'feed.php?mode=topics_active', array(), false); +		$crawler = self::request('GET', 'app.php/feed/topics_active', array(), false);  		self::assert_response_xml();  		self::$init_values['admin']['topics_active_value'] = $crawler->filterXPath('//entry')->count(); - -  	}  	public function test_setup_forums() @@ -138,7 +136,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form = $crawler->selectButton('update')->form(array(  			'forum_perm_from'	=> 2,  		)); -		$crawler = self::submit($form); +		self::submit($form);  		$this->load_ids(array(  			'forums' => array( @@ -155,7 +153,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form = $crawler->selectButton('update')->form(array(  			'forum_perm_from'	=> 2,  		)); -		$crawler = self::submit($form); +		self::submit($form);  		// 'Feeds #news' will be used for feed.php?mode=news  		$crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}"); @@ -166,9 +164,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form = $crawler->selectButton('update')->form(array(  			'forum_perm_from'	=> 2,  		)); -		$crawler = self::submit($form); +		self::submit($form); -		// 'Feeds #exclude' will not be displayed on feed.php?mode=forums +		// 'Feeds #exclude' will not be displayed on app.php/feed/forums  		$crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}");  		$form = $crawler->selectButton('addforum')->form(array(  			'forum_name'	=> 'Feeds #exclude', @@ -177,7 +175,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form = $crawler->selectButton('update')->form(array(  			'forum_perm_from'	=> 2,  		)); -		$crawler = self::submit($form); +		self::submit($form);  	}  	public function test_setup_config_after_forums() @@ -201,7 +199,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form['feed_exclude_id']->select(array($this->data['forums']['Feeds #exclude']));  		$crawler = self::submit($form); -		$this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text()); +		self::assertContainsLang('CONFIG_UPDATED', $crawler->filter('.successbox')->text());  	}  	public function test_feeds_empty() @@ -272,6 +270,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  					'id' => $this->data['forums']['Feeds #exclude'],  					'contents_lang' => array('NO_FEED'),  					'invalid' => true, +					'response_code' => 404,  				),  			),  			't' => array( @@ -279,6 +278,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  					'id' => $this->data['topics']['Feeds #exclude - Topic #1'],  					'contents_lang' => array('NO_FEED'),  					'invalid' => true, +					'response_code' => 404,  				),  			),  			'overall' => array( @@ -331,7 +331,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$post = $this->create_topic($this->data['forums']['Feeds #news'], 'Feeds #news - Topic #2', 'This is a test topic posted by the testing framework.');  		$crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); -		$this->assertContains('Feeds #news - Topic #2', $crawler->filter('html')->text()); +		self::assertContains('Feeds #news - Topic #2', $crawler->filter('html')->text());  		$this->data['topics']['Feeds #news - Topic #2'] = (int) $post['topic_id'];  		$this->data['posts']['Feeds #news - Topic #2'] = (int) $this->get_parameter_from_link($crawler->filter('.post')->selectLink($this->lang('POST', '', ''))->link()->getUri(), 'p'); @@ -339,7 +339,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$post2 = $this->create_post($this->data['forums']['Feeds #news'], $post['topic_id'], 'Re: Feeds #news - Topic #2', 'This is a test post posted by the testing framework.');  		$crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); -		$this->assertContains('Re: Feeds #news - Topic #2', $crawler->filter('html')->text()); +		self::assertContains('Re: Feeds #news - Topic #2', $crawler->filter('html')->text());  		$this->data['posts']['Re: Feeds #news - Topic #2'] = (int) $post2['post_id'];  	} @@ -495,7 +495,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$post2 = $this->create_post($this->data['forums']['Feeds #1'], $post['topic_id'], 'Re: Feeds #1 - Topic #2', 'This is a test post posted by the testing framework.');  		$crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); -		$this->assertContains('Re: Feeds #1 - Topic #2', $crawler->filter('html')->text()); +		self::assertContains('Re: Feeds #1 - Topic #2', $crawler->filter('html')->text());  		$this->data['posts']['Re: Feeds #1 - Topic #2'] = (int) $post2['post_id'];  	} @@ -516,14 +516,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$this->add_lang('posting');  		$crawler = self::request('GET', "posting.php?mode=delete&f={$this->data['forums']['Feeds #1']}&p={$this->data['posts']['Re: Feeds #1 - Topic #2']}&sid={$this->sid}"); -		$this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text()); +		self::assertContainsLang('DELETE_PERMANENTLY', $crawler->text());  		$form = $crawler->selectButton('Yes')->form();  		$crawler = self::submit($form); -		$this->assertContainsLang('POST_DELETED', $crawler->text()); +		self::assertContainsLang('POST_DELETED', $crawler->text());  		$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1 - Topic #2']}&sid={$this->sid}"); -		$this->assertContains($this->lang('POST_DISPLAY', '', ''), $crawler->text()); +		self::assertContains($this->lang('POST_DISPLAY', '', ''), $crawler->text());  	}  	public function test_feeds_softdeleted_post_admin() @@ -615,15 +615,15 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$this->add_lang('posting');  		$crawler = $this->get_quickmod_page($this->data['topics']['Feeds #1 - Topic #2'], 'DELETE_TOPIC'); -		$this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text()); +		self::assertContainsLang('DELETE_PERMANENTLY', $crawler->text());  		$this->add_lang('mcp');  		$form = $crawler->selectButton('Yes')->form();  		$crawler = self::submit($form); -		$this->assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text()); +		self::assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text());  		$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1 - Topic #2']}&sid={$this->sid}"); -		$this->assertContains('Feeds #1 - Topic #2', $crawler->filter('h2')->text()); +		self::assertContains('Feeds #1 - Topic #2', $crawler->filter('h2')->text());  	}  	public function test_feeds_softdeleted_topic_admin() @@ -716,8 +716,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  			't' => array(  				array(  					'id' => $this->data['topics']['Feeds #1 - Topic #2'], -					'contents_lang' => array('SORRY_AUTH_READ'), +					'contents_lang' => array('SORRY_AUTH_READ_TOPIC'),  					'invalid' => true, +					'response_code' => 403,  				),  			),  			'overall' => array( @@ -758,10 +759,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		// Test creating a reply  		$this->login('disapprove_user'); -		$post2 = $this->create_post($this->data['forums']['Feeds #1.1'], $post['topic_id'], 'Re: Feeds #1.1 - Topic #2', 'This is a test post posted by the testing framework.', array(), 'POST_STORED_MOD'); +		$this->create_post($this->data['forums']['Feeds #1.1'], $post['topic_id'], 'Re: Feeds #1.1 - Topic #2', 'This is a test post posted by the testing framework.', array(), 'POST_STORED_MOD');  		$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Feeds #1.1 - Topic #2']}&sid={$this->sid}"); -		$this->assertNotContains('Re: Feeds #1.1 - Topic #2', $crawler->filter('html')->text()); +		self::assertNotContains('Re: Feeds #1.1 - Topic #2', $crawler->filter('html')->text());  	}  	public function test_feeds_unapproved_post_admin() @@ -853,7 +854,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$this->data['topics']['Feeds #1 - Topic #3'] = (int) $post['topic_id'];  		$crawler = self::request('GET', "viewforum.php?f={$this->data['forums']['Feeds #1.1']}&sid={$this->sid}"); -		$this->assertNotContains('Feeds #1.1 - Topic #3', $crawler->filter('html')->text()); +		self::assertNotContains('Feeds #1.1 - Topic #3', $crawler->filter('html')->text());  		$this->logout();  		$this->set_flood_interval(15); @@ -869,10 +870,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$form = $crawler->selectButton('Submit')->form();  		$values = $form->getValues(); -		$values["config[flood_interval]"] = $flood_interval; +		$values['config[flood_interval]'] = $flood_interval;  		$form->setValues($values);  		$crawler = self::submit($form); -		$this->assertGreaterThan(0, $crawler->filter('.successbox')->count()); +		self::assertGreaterThan(0, $crawler->filter('.successbox')->count());  		$this->logout();  	} @@ -964,8 +965,9 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  			't' => array(  				array(  					'id' => $this->data['topics']['Feeds #1.1 - Topic #3'], -					'contents_lang' => array('SORRY_AUTH_READ'), +					'contents_lang' => array('SORRY_AUTH_READ_TOPIC'),  					'invalid' => true, +					'response_code' => 403,  				),  			),  			'overall' => array( @@ -1004,7 +1006,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$post = $this->create_topic($this->data['forums']['Feeds #1'], 'Feeds #1 - Topic #3', 'This is a test topic posted by the testing framework. [attachment=0]Attachment #0[/attachment]', array('upload_files' => 1));  		$crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); -		$this->assertContains('Feeds #1 - Topic #3', $crawler->filter('html')->text()); +		self::assertContains('Feeds #1 - Topic #3', $crawler->filter('html')->text());  		$this->data['topics']['Feeds #1 - Topic #3'] = (int) $post['topic_id'];  	} @@ -1222,7 +1224,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		$post2 = $this->create_post($this->data['forums']['Feeds #1'], $this->data['topics']['Feeds #1 - Topic #3'], 'Re: Feeds #1 - Topic #3-1', 'This is a test post posted by the testing framework. [attachment=0]Attachment #0[/attachment]');  		$crawler = self::request('GET', "viewtopic.php?t={$post2['topic_id']}&sid={$this->sid}"); -		$this->assertContains('Re: Feeds #1 - Topic #3-1', $crawler->filter('html')->text()); +		self::assertContains('Re: Feeds #1 - Topic #3-1', $crawler->filter('html')->text());  		$this->data['posts']['Re: Feeds #1 - Topic #3-1'] = (int) $post2['post_id'];  	} @@ -1322,9 +1324,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		{  			foreach ($feeds as $feed_data)  			{ -				if ($mode === 'f' || $mode === 't') +				if ($mode === 'f') +				{ +					$params = "/forum/{$feed_data['id']}"; +					$this->assert_feed($params, $feed_data); +				} +				else if ($mode === 't')  				{ -					$params = "?{$mode}={$feed_data['id']}"; +					$params = "/topic/{$feed_data['id']}";  					$this->assert_feed($params, $feed_data);  				}  				else @@ -1348,10 +1355,10 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  						case 'news':  							break;  						default: -							$this->fail('Unsupported feed mode: ' . $mode); +							self::fail('Unsupported feed mode: ' . $mode);  					} -					$params = "?mode={$mode}"; +					$params = "/{$mode}";  					$this->assert_feed($params, $feed_data);  				}  			} @@ -1360,19 +1367,19 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  	protected function assert_feed($params, $data)  	{ -		$crawler = self::request('GET', 'feed.php' . $params, array(), false); +		$crawler = self::request('GET', 'app.php/feed' . $params, array(), false);  		if (empty($data['invalid']))  		{  			self::assert_response_xml(); -			$this->assertEquals($data['nb_entries'], $crawler->filter('entry')->count(), "Tested feed : 'feed.php{$params}'"); +			self::assertEquals($data['nb_entries'], $crawler->filter('entry')->count(), "Tested feed : 'app.php/feed{$params}'");  			if (!empty($data['xpath']))  			{  				foreach($data['xpath'] as $xpath => $count_expected)  				{ -					$this->assertCount($count_expected, $crawler->filterXPath($xpath), "Tested feed : 'feed.php{$params}', Search for {$xpath}"); +					self::assertCount($count_expected, $crawler->filterXPath($xpath), "Tested feed : 'app.php/feed{$params}', Search for {$xpath}");  				}  			} @@ -1381,7 +1388,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  				foreach($data['contents'] as $entry_id => $string)  				{  					$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text(); -					$this->assertContains($string, $content, "Tested feed : 'feed.php{$params}'"); +					self::assertContains($string, $content, "Tested feed : 'app.php/feed{$params}'");  				}  			} @@ -1390,7 +1397,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  				foreach($data['contents_lang'] as $entry_id => $string)  				{  					$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text(); -					$this->assertContainsLang($string, $content, "Tested feed : 'feed.php{$params}'"); +					self::assertContainsLang($string, $content, "Tested feed : 'app.php/feed{$params}'");  				}  			} @@ -1398,21 +1405,21 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  			{  				foreach($data['attachments'] as $entry_id => $attachments)  				{ +					$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();  					foreach ($attachments as $i => $attachment)  					{ -						$content = $crawler->filterXPath("//entry[{$entry_id}]/content")->text();  						$url = self::$root_url . "download/file.php?id={$attachment['id']}";  						$string = "Attachment #{$i}";  						if ($attachment['displayed'])  						{ -							$this->assertContains($url, $content, "Tested feed : 'feed.php{$params}'"); -							$this->assertNotContains($string, $content, "Tested feed : 'feed.php{$params}'"); +							self::assertContains($url, $content, "Tested feed : 'app.php/feed{$params}'"); +							self::assertNotContains($string, $content, "Tested feed : 'app.php/feed{$params}'");  						}  						else  						{ -							$this->assertContains($string, $content, "Tested feed : 'feed.php{$params}'"); -							$this->assertNotContains($url, $content, "Tested feed : 'feed.php{$params}'"); +							self::assertContains($string, $content, "Tested feed : 'app.php/feed{$params}'"); +							self::assertNotContains($url, $content, "Tested feed : 'app.php/feed{$params}'");  						}  					}  				} @@ -1420,14 +1427,14 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  		}  		else  		{ -			self::assert_response_html(); +			self::assert_response_html($data['response_code'] ?: 202);  			if (!empty($data['contents_lang']))  			{ +				$content = $crawler->filter('html')->text();  				foreach($data['contents_lang'] as $string)  				{ -					$content = $crawler->filter('html')->text(); -					$this->assertContainsLang($string, $content, "Tested feed : 'feed.php{$params}'"); +					self::assertContainsLang($string, $content, "Tested feed : 'app.php/feed{$params}'");  				}  			}  		} @@ -1445,7 +1452,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  			$result = $this->db->sql_query($sql);  			while ($row = $this->db->sql_fetchrow($result))  			{ -				if (in_array($row['forum_name'], $data['forums'])) +				if (in_array($row['forum_name'], $data['forums'], false))  				{  					$this->data['forums'][$row['forum_name']] = (int) $row['forum_id'];  				} @@ -1461,7 +1468,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  			$result = $this->db->sql_query($sql);  			while ($row = $this->db->sql_fetchrow($result))  			{ -				if (in_array($row['topic_title'], $data['topics'])) +				if (in_array($row['topic_title'], $data['topics'], false))  				{  					$this->data['topics'][$row['topic_title']] = (int) $row['topic_id'];  				} @@ -1478,7 +1485,7 @@ class phpbb_functional_feed_test extends phpbb_functional_test_case  			$result = $this->db->sql_query($sql);  			while ($row = $this->db->sql_fetchrow($result))  			{ -				if (in_array($row['post_subject'], $data['posts'])) +				if (in_array($row['post_subject'], $data['posts'], false))  				{  					$this->data['posts'][$row['post_subject']] = (int) $row['post_id'];  					$post_ids[] = (int) $row['post_id']; diff --git a/tests/functional/fileupload_remote_test.php b/tests/functional/fileupload_remote_test.php index 6ece150b23..b70d49cddd 100644 --- a/tests/functional/fileupload_remote_test.php +++ b/tests/functional/fileupload_remote_test.php @@ -11,13 +11,29 @@  *  */ -require_once __DIR__ . '/../../phpBB/includes/functions_upload.php'; -  /**   * @group functional   */  class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case  { +	/** @var \phpbb\filesystem\filesystem_interface */ +	protected $filesystem; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; +  	public function setUp()  	{  		parent::setUp(); @@ -25,19 +41,28 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case  		// URL  		// Global $config required by unique_id -		// Global $user required by fileupload::remote_upload -		global $config, $user; +		global $config, $phpbb_root_path, $phpEx;  		if (!is_array($config))  		{ -			$config = array(); +			$config = new \phpbb\config\config(array());  		}  		$config['rand_seed'] = '';  		$config['rand_seed_last_update'] = time() + 600; +		$config['remote_upload_verify'] = 0; + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$this->request = $this->getMock('\phpbb\request\request'); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; -		$user = new phpbb_mock_user(); -		$user->lang = new phpbb_mock_lang(); +		$container = new phpbb_mock_container_builder(); +		$container->set('files.filespec', new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path)); +		$this->factory = new \phpbb\files\factory($container); +		$container->set('files.factory', $this->factory); +		$container->set('files.types.remote', new \phpbb\files\types\remote($config, $this->factory, $this->language, $this->php_ini, $this->request, $phpbb_root_path)); +		$this->phpbb_root_path = $phpbb_root_path;  	}  	public function tearDown() @@ -49,30 +74,47 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case  	public function test_invalid_extension()  	{ -		$upload = new fileupload('', array('jpg'), 100); -		$file = $upload->remote_upload(self::$root_url . 'develop/blank.gif'); +		/** @var \phpbb\files\upload $upload */ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_error_prefix('') +			->set_allowed_extensions(array('jpg')) +			->set_max_filesize(100); +		$file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/blank.gif');  		$this->assertEquals('URL_INVALID', $file->error[0]);  	}  	public function test_empty_file()  	{ -		$upload = new fileupload('', array('jpg'), 100); -		$file = $upload->remote_upload(self::$root_url . 'develop/blank.jpg'); +		/** @var \phpbb\files\upload $upload */ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_error_prefix('') +			->set_allowed_extensions(array('jpg')) +			->set_max_filesize(100); +		$file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/blank.jpg');  		$this->assertEquals('EMPTY_REMOTE_DATA', $file->error[0]);  	}  	public function test_successful_upload()  	{ -		$upload = new fileupload('', array('gif'), 1000); -		$file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif'); +		/** @var \phpbb\files\upload $upload */ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_error_prefix('') +			->set_allowed_extensions(array('gif')) +			->set_max_filesize(1000); +		$file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');  		$this->assertEquals(0, sizeof($file->error)); -		$this->assertTrue(file_exists($file->filename)); +		$this->assertTrue(file_exists($file->get('filename'))); +		$this->assertTrue($file->is_uploaded());  	}  	public function test_too_large()  	{ -		$upload = new fileupload('', array('gif'), 100); -		$file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif'); +		/** @var \phpbb\files\upload $upload */ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_error_prefix('') +			->set_allowed_extensions(array('gif')) +			->set_max_filesize(100); +		$file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');  		$this->assertEquals(1, sizeof($file->error));  		$this->assertEquals('WRONG_FILESIZE', $file->error[0]);  	} diff --git a/tests/functional/fixtures/ext/foo/bar/acp/main_info.php b/tests/functional/fixtures/ext/foo/bar/acp/main_info.php index ec378e0e75..371ab7c967 100644 --- a/tests/functional/fixtures/ext/foo/bar/acp/main_info.php +++ b/tests/functional/fixtures/ext/foo/bar/acp/main_info.php @@ -28,7 +28,6 @@ class main_info  		return array(  			'filename'	=> 'foo\bar\acp\main_module',  			'title'		=> 'ACP_FOOBAR_TITLE', -			'version'	=> '1.0.0',  			'modes'		=> array(  				'mode'		=> array('title' => 'ACP_FOOBAR_MODE', 'auth' => '', 'cat' => array('ACP_FOOBAR_TITLE')),  			), diff --git a/tests/functional/fixtures/ext/foo/bar/config/services.yml b/tests/functional/fixtures/ext/foo/bar/config/services.yml index d35be7955a..495c775a1f 100644 --- a/tests/functional/fixtures/ext/foo/bar/config/services.yml +++ b/tests/functional/fixtures/ext/foo/bar/config/services.yml @@ -2,13 +2,13 @@ services:      foo_bar.controller:          class: foo\bar\controller\controller          arguments: -            - @controller.helper -            - @path_helper -            - @template -            - @config -            - @user -            - %core.root_path% -            - %core.php_ext% +            - '@controller.helper' +            - '@path_helper' +            - '@template' +            - '@config' +            - '@user' +            - '%core.root_path%' +            - '%core.php_ext%'      foo_bar.listener.permission:          class: foo\bar\event\permission diff --git a/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php b/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php index d34244f800..4c74442639 100644 --- a/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php +++ b/tests/functional/fixtures/ext/foo/bar/ucp/main_info.php @@ -20,7 +20,6 @@ class main_info  		return array(  			'filename'	=> '\foo\bar\ucp\main_module',  			'title'		=> 'ACP_FOOBAR_TITLE', -			'version'	=> '1.0.0',  			'modes'		=> array(  				'mode'		=> array('title' => 'ACP_FOOBAR_MODE', 'auth' => '', 'cat' => array('ACP_FOOBAR_TITLE')),  			), diff --git a/tests/functional/forum_style_test.php b/tests/functional/forum_style_test.php index 65be94f4d0..b3c1115b7f 100644 --- a/tests/functional/forum_style_test.php +++ b/tests/functional/forum_style_test.php @@ -16,16 +16,28 @@  */  class phpbb_functional_forum_style_test extends phpbb_functional_test_case  { +	public function test_font_awesome_style() +	{ +		$crawler = self::request('GET', 'viewtopic.php?t=1&f=2'); +		$this->assertContains('font-awesome.min', $crawler->filter('head > link[rel=stylesheet]')->eq(0)->attr('href')); + +		$crawler = self::request('GET', 'viewtopic.php?t=1'); +		$this->assertContains('font-awesome.min', $crawler->filter('head > link[rel=stylesheet]')->eq(0)->attr('href')); + +		$crawler = self::request('GET', 'viewtopic.php?t=1&view=next'); +		$this->assertContains('font-awesome.min', $crawler->filter('head > link[rel=stylesheet]')->eq(0)->attr('href')); +	} +  	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')); +		$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));  		$crawler = self::request('GET', 'viewtopic.php?t=1'); -		$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); +		$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));  		$crawler = self::request('GET', 'viewtopic.php?t=1&view=next'); -		$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); +		$this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));  	}  	public function test_custom_forum_style() @@ -35,13 +47,13 @@ class phpbb_functional_forum_style_test extends phpbb_functional_test_case  		$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')); +		$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));  		$crawler = self::request('GET', 'viewtopic.php?t=1'); -		$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); +		$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->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')); +		$this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->eq(1)->attr('href'));  		$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 0 WHERE forum_id = 2');  		$this->delete_style(2, 'test_style'); diff --git a/tests/functional/notification_test.php b/tests/functional/notification_test.php index d4c61cc062..8751de8016 100644 --- a/tests/functional/notification_test.php +++ b/tests/functional/notification_test.php @@ -21,15 +21,15 @@ class phpbb_functional_notification_test extends phpbb_functional_test_case  		return array(  			// Rows inserted by phpBB/install/schemas/schema_data.sql  			// Also see PHPBB3-11460 -			array('notification.type.post_notification', true), -			array('notification.type.topic_notification', true), +			array('notification.type.post_notification.method.board', true), +			array('notification.type.topic_notification.method.board', true),  			array('notification.type.post_notification.method.email', true),  			array('notification.type.topic_notification.method.email', true),  			// Default behaviour for in-board notifications:  			// If user did not opt-out, in-board notifications are on. -			array('notification.type.bookmark_notification', true), -			array('notification.type.quote_notification', true), +			array('notification.type.bookmark_notification.method.board', true), +			array('notification.type.quote_notification.method.board', true),  			// Default behaviour for email notifications:  			// If user did not opt-in, email notifications are off. diff --git a/tests/functional/permission_roles_test.php b/tests/functional/permission_roles_test.php new file mode 100644 index 0000000000..e6506fb37c --- /dev/null +++ b/tests/functional/permission_roles_test.php @@ -0,0 +1,84 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group functional +*/ +class functional_permission_roles_test extends phpbb_functional_test_case +{ +	public function data_permission_roles() +	{ +		return array( +			array( +				array(0, 14), +				array(17, 17), +				array( +					'role[5][1]'	=> 14, +				) +			), +			array( +				array(14, 14), +				array(17, 17), +				array( +					'role[5][1]'	=> 0, +				) +			), +			array( +				array(0, 14), +				array(17, 17) +			), +		); +	} +	/** +	 * @dataProvider data_permission_roles +	 */ +	public function test_permission_roles($admin_roles, $guest_roles, $set_values = array()) +	{ +		$this->login(); +		$this->admin_login(); +		$this->add_lang('acp/permissions'); +		$crawler = self::request('GET', 'adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid); + +		// Select forums +		$form = $crawler->filter('form[id=select_victim]')->form(); +		$form['forum_id']->setValue(array(1,2)); +		$crawler = self::$client->submit($form); + +		// Select administrators and guests +		$groups_form = $crawler->filter('form[id=groups]')->form(); +		$groups_form['group_id']->setValue(array(1,5)); + +		$crawler = self::submit($groups_form); +		$form = $crawler->filter('form')->form(); +		$values = $form->getValues(); + +		// Check default settings +		$this->assertEquals($admin_roles[0], $values['role[5][1]']); +		$this->assertEquals($admin_roles[1], $values['role[5][2]']); +		$this->assertEquals($guest_roles[0], $values['role[1][1]']); +		$this->assertEquals($guest_roles[1], $values['role[1][2]']); + +		// Set admin to full access on category +		foreach ($set_values as $key => $value) +		{ +			$form[$key]->setValue($value); +		} + +		$form_values = $form->getValues(); +		$form_values['action[apply_all_permissions]'] = true; +		$crawler = self::request('POST', 'adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid, $form_values); +		$this->assertContainsLang('AUTH_UPDATED', $crawler->text()); + +		$this->logout(); +	} +} diff --git a/tests/functional/plupload_test.php b/tests/functional/plupload_test.php index d358681ad1..9d284a7e57 100644 --- a/tests/functional/plupload_test.php +++ b/tests/functional/plupload_test.php @@ -107,11 +107,11 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case  			if ($i < self::CHUNKS - 1)  			{ -				$this->assertContains('{"jsonrpc":"2.0","id":"id","result":null}', self::$client->getResponse()->getContent()); +				$this->assertContains('{"jsonrpc":"2.0","id":"id","result":null}', self::get_content());  			}  			else  			{ -				$response = json_decode(self::$client->getResponse()->getContent(), true); +				$response = json_decode(self::get_content(), true);  				$this->assertEquals('valid.jpg', $response['data'][0]['real_filename']);  			} @@ -134,7 +134,8 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case  			'error' => UPLOAD_ERR_OK,  		); -		$crawler = self::$client->request( +		self::$client->setServerParameter('HTTP_X_PHPBB_USING_PLUPLOAD', '1'); +		self::$client->request(  			'POST',  			$url . '&sid=' . $this->sid,  			array( @@ -144,11 +145,10 @@ class phpbb_functional_plupload_test extends phpbb_functional_test_case  				'real_filename' => 'valid.jpg',  				'add_file' => $this->lang('ADD_FILE'),  			), -			array('fileupload' => $file), -			array('X-PHPBB-USING-PLUPLOAD' => '1') +			array('fileupload' => $file)  		); -		$response = json_decode(self::$client->getResponse()->getContent(), true); +		$response = json_decode(self::get_content(), true);  		$this->assertEquals('valid.jpg', $response['data'][0]['real_filename']);  	}  } diff --git a/tests/functional/posting_test.php b/tests/functional/posting_test.php index 914233240e..9dd8a1dc91 100644 --- a/tests/functional/posting_test.php +++ b/tests/functional/posting_test.php @@ -45,14 +45,6 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case  		self::create_post(2,  			1, -			'Unsupported characters', -			"This is a test with these weird characters: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6", -			array(), -			'Your message contains the following unsupported characters' -		); - -		self::create_post(2, -			1,  			"Unsupported: \xF0\x9F\x88\xB3 \xF0\x9F\x9A\xB6",  			'This is a test with emoji characters in the topic title.',  			array(), @@ -60,6 +52,40 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case  		);  	} +	public function test_supported_unicode_characters() +	{ +		$this->login(); + +		$post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.'); +		$this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', "This is a test with these weird characters: \xF0\x9F\x84\x90 \xF0\x9F\x84\x91"); +		$crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); +		$this->assertContains("\xF0\x9F\x84\x90 \xF0\x9F\x84\x91", $crawler->text()); +	} + +	public function test_html_entities() +	{ +		$this->login(); + +		$post = $this->create_topic(2, 'Test Topic 1', 'This is a test topic posted by the testing framework.'); +		$this->create_post(2, $post['topic_id'], 'Re: Test Topic 1', '😀'); +		$crawler = self::request('GET', "viewtopic.php?t={$post['topic_id']}&sid={$this->sid}"); +		$this->assertContains('😀', $crawler->text()); +	} + +	public function test_quote() +	{ +		$text     = 'Test post </textarea>"\' &&amp;'; +		$expected = "(\\[quote=admin[^\\]]*\\]\n" . preg_quote($text) . "\n\\[/quote\\])"; + +		$this->login(); +		$topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); +		$post  = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + +		$crawler = self::request('GET', "posting.php?mode=quote&f=2&t={$post['topic_id']}&p={$post['post_id']}&sid={$this->sid}"); + +		$this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); +	} +  	/**  	* @testdox max_quote_depth is applied to the text populating the posting form  	*/ @@ -67,10 +93,10 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case  	{  		$text = '0[quote]1[quote]2[/quote]1[/quote]0';  		$expected = array( -			0 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', -			1 => '[quote="admin"]00[/quote]', -			2 => '[quote="admin"]0[quote]11[/quote]0[/quote]', -			3 => '[quote="admin"]0[quote]1[quote]2[/quote]1[/quote]0[/quote]', +			0 => '0[quote]1[quote]2[/quote]1[/quote]0', +			1 => '00', +			2 => '0[quote]11[/quote]0', +			3 => '0[quote]1[quote]2[/quote]1[/quote]0',  		);  		$this->login(); @@ -83,7 +109,10 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case  		{  			$this->set_quote_depth($quote_depth);  			$crawler = self::request('GET', $quote_url); -			$this->assertContains($expected_text, $crawler->filter('textarea#message')->text()); +			$this->assertRegexp( +				"(\\[quote=admin[^\\]]*\\]\n?" . preg_quote($expected_text) . "\n?\\[/quote\\])", +				$crawler->filter('textarea#message')->text() +			);  		}  	} @@ -156,4 +185,65 @@ class phpbb_functional_posting_test extends phpbb_functional_test_case  		$crawler = self::submit($form);  		$this->assertEquals(1, $crawler->filter('.successbox')->count());  	} + +	public function test_ticket_8420() +	{ +		$text = '[b][url=http://example.org] :arrow: here[/url][/b]'; + +		$this->login(); +		$crawler = self::request('GET', 'posting.php?mode=post&f=2'); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'Test subject', +			'message' => $text +		)); +		$crawler = self::submit($form); +		$this->assertEquals($text, $crawler->filter('#message')->text()); +	} + +	public function test_old_signature_in_preview() +	{ +		$sql = 'UPDATE ' . USERS_TABLE . " +			SET user_sig = '[b:2u8sdcwb]My signature[/b:2u8sdcwb]', +				user_sig_bbcode_uid = '2u8sdcwb', +				user_sig_bbcode_bitfield = 'QA==' +			WHERE user_id = 2"; +		$this->get_db()->sql_query($sql); + +		$this->login(); +		$crawler = self::request('GET', 'posting.php?mode=post&f=2'); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'Test subject', +			'message' => 'My post', +		)); +		$crawler = self::submit($form); +		$this->assertContains( +			'<span style="font-weight: bold">My signature</span>', +			$crawler->filter('#preview .signature')->html() +		); +	} + +	/** +	* @ticket PHPBB3-10628 +	*/ +	public function test_www_links_preview() +	{ +		$text = 'www.example.org'; +		$url  = 'http://' . $text; + +		$this->add_lang('posting'); +		$this->login(); + +		$crawler = self::request('GET', 'posting.php?mode=post&f=2'); +		$form = $crawler->selectButton('Preview')->form(array( +			'subject' => 'Test subject', +			'message' => $text +		)); +		$crawler = self::submit($form); + +		// Test that the textarea remains unchanged +		$this->assertEquals($text, $crawler->filter('#message')->text()); + +		// Test that the preview contains the correct link +		$this->assertEquals($url, $crawler->filter('#preview a')->attr('href')); +	}  } diff --git a/tests/functional/private_messages_test.php b/tests/functional/private_messages_test.php index 1f6dc3a979..7fda26fb49 100644 --- a/tests/functional/private_messages_test.php +++ b/tests/functional/private_messages_test.php @@ -66,4 +66,45 @@ class phpbb_functional_private_messages_test extends phpbb_functional_test_case  		$crawler = self::submit($form);  		$this->assertContains($this->lang('CONFIG_UPDATED'), $crawler->filter('.successbox')->text());  	} + +	public function test_quote_post() +	{ +		$text = 'Test post'; + +		$this->login(); +		$topic = $this->create_topic(2, 'Test Topic 1', 'Test topic'); +		$post  = $this->create_post(2, $topic['topic_id'], 'Re: Test Topic 1', $text); + +		$expected = '(\\[quote=admin post_id=' . $post['post_id'] . ' time=\\d+ user_id=2\\]' . $text . '\\[/quote\\])'; + +		$crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quotepost&p=' . $post['post_id'] . '&sid=' . $this->sid); + +		$this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); +	} + +	public function test_quote_pm() +	{ +		$text     = 'This is a test private message sent by the testing framework.'; +		$expected = "(\\[quote=admin time=\\d+ user_id=2\\]\n" . $text . "\n\\[/quote\\])"; + +		$this->login(); +		$message_id = $this->create_private_message('Test', $text, array(2)); + +		$crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=quote&p=' . $message_id . '&sid=' . $this->sid); + +		$this->assertRegexp($expected, $crawler->filter('textarea#message')->text()); +	} + +	public function test_quote_forward() +	{ +		$text     = 'This is a test private message sent by the testing framework.'; +		$expected = "[quote=admin]\n" . $text . "\n[/quote]"; + +		$this->login(); +		$message_id = $this->create_private_message('Test', $text, array(2)); + +		$crawler = self::request('GET', 'ucp.php?i=pm&mode=compose&action=forward&f=0&p=' . $message_id . '&sid=' . $this->sid); + +		$this->assertContains($expected, $crawler->filter('textarea#message')->text()); +	}  } diff --git a/tests/functional/report_post_captcha_test.php b/tests/functional/report_post_captcha_test.php index 93a03bd931..36a1a9ee4d 100644 --- a/tests/functional/report_post_captcha_test.php +++ b/tests/functional/report_post_captcha_test.php @@ -18,12 +18,13 @@ class phpbb_functional_report_post_captcha_test extends phpbb_functional_test_ca  {  	public function test_guest_report_post()  	{ -		$crawler = self::request('GET', 'report.php?f=2&p=1'); +		$crawler = self::request('GET', 'app.php/post/1/report', array(), false); +		$this->assert_response_html(403);  		$this->add_lang('mcp');  		$this->assertContains($this->lang('USER_CANNOT_REPORT'), $crawler->filter('html')->text());  		$this->set_reporting_guest(1); -		$crawler = self::request('GET', 'report.php?f=2&p=1'); +		$crawler = self::request('GET', 'app.php/post/1/report');  		$this->assertContains($this->lang('CONFIRM_CODE'), $crawler->filter('html')->text());  		$this->set_reporting_guest(-1);  	} @@ -31,7 +32,7 @@ class phpbb_functional_report_post_captcha_test extends phpbb_functional_test_ca  	public function test_user_report_post()  	{  		$this->login(); -		$crawler = self::request('GET', 'report.php?f=2&p=1'); +		$crawler = self::request('GET', 'app.php/post/1/report');  		$this->assertNotContains($this->lang('CONFIRM_CODE'), $crawler->filter('html')->text());  		$this->add_lang('mcp'); diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php index f1e9b517d4..48c444fb76 100644 --- a/tests/functional/search/base.php +++ b/tests/functional/search/base.php @@ -36,6 +36,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case  		$this->login();  		$this->admin_login(); +		$this->create_search_index('\phpbb\search\fulltext_native'); +  		$post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.');  		$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=settings&sid=' . $this->sid); @@ -58,6 +60,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case  				$this->delete_topic($post['topic_id']);  				$this->markTestSkipped("Search backend is not supported/running");  			} +  			$this->create_search_index();  		} @@ -72,7 +75,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case  		$this->delete_topic($post['topic_id']);  	} -	protected function create_search_index() +	protected function create_search_index($backend = null)  	{  		$this->add_lang('acp/search');  		$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid); @@ -80,7 +83,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case  		$form_values = $form->getValues();  		$form_values = array_merge($form_values,  			array( -				'search_type'	=> $this->search_backend, +				'search_type'	=> ( ($backend === null) ? $this->search_backend : $backend ),  				'action'		=> 'create',  			)  		); diff --git a/tests/functional/visit_installer_test.php b/tests/functional/visit_installer_test.php new file mode 100644 index 0000000000..b4a75c0b51 --- /dev/null +++ b/tests/functional/visit_installer_test.php @@ -0,0 +1,30 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_visit_installer_test extends phpbb_functional_test_case +{ +	public function test_visit_installer() +	{ +		self::request('GET', 'install/', [], false); +		$this->assertContains('<meta http-equiv="refresh" content="0; url=./app.php" />', $this->get_content()); + +		self::request('GET', 'install/index.html', [], false); +		$this->assertContains('<meta http-equiv="refresh" content="0; url=./app.php" />', $this->get_content()); + +		self::request('GET', 'install/app.php'); +		$this->assertContains('installation system', $this->get_content()); +	} +} diff --git a/tests/functions/build_hidden_fields_for_query_params_test.php b/tests/functions/build_hidden_fields_for_query_params_test.php index 14cb4b9a94..aee7a569d4 100644 --- a/tests/functions/build_hidden_fields_for_query_params_test.php +++ b/tests/functions/build_hidden_fields_for_query_params_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_build_hidden_fields_for_query_params_test extends phpbb_test_case  {  	public function build_hidden_fields_for_query_params_test_data() diff --git a/tests/functions/build_url_test.php b/tests/functions/build_url_test.php index a59b94c744..91a4a9ec66 100644 --- a/tests/functions/build_url_test.php +++ b/tests/functions/build_url_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_build_url_test extends phpbb_test_case  {  	protected function setUp() @@ -29,7 +27,7 @@ class phpbb_build_url_test extends phpbb_test_case  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			new \phpbb\filesystem\filesystem(),  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			'php' diff --git a/tests/functions/convert_30_dbms_to_31_test.php b/tests/functions/convert_30_dbms_to_31_test.php index 729c0a82f0..456eb64461 100644 --- a/tests/functions/convert_30_dbms_to_31_test.php +++ b/tests/functions/convert_30_dbms_to_31_test.php @@ -11,21 +11,17 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_convert_30_dbms_to_31_test extends phpbb_test_case  {  	public function convert_30_dbms_to_31_data()  	{  		return array( -			array('mssql'),  			array('mssql_odbc'),  			array('mssqlnative'),  			array('mysql'),  			array('mysqli'),  			array('oracle'),  			array('postgres'), -			array('sqlite'),  		);  	} diff --git a/tests/functions/generate_string_list.php b/tests/functions/generate_string_list.php index cd1e37618a..6eddb1395e 100644 --- a/tests/functions/generate_string_list.php +++ b/tests/functions/generate_string_list.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_generate_string_list_test extends phpbb_test_case  {  	public $user; @@ -22,7 +19,12 @@ class phpbb_generate_string_list_test extends phpbb_test_case  	{  		parent::setUp(); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$this->user = $user;  		$this->user->data = array('user_lang' => 'en');  		$this->user->add_lang('common');  	} @@ -36,7 +38,7 @@ class phpbb_generate_string_list_test extends phpbb_test_case  			),  			array(  				array('A'), -				'A',	 +				'A',  			),  			array(  				array(2 => 'A', 3 => 'B'), diff --git a/tests/functions/get_formatted_filesize_test.php b/tests/functions/get_formatted_filesize_test.php index 635753d737..290515b64f 100644 --- a/tests/functions/get_formatted_filesize_test.php +++ b/tests/functions/get_formatted_filesize_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_get_formatted_filesize_test extends phpbb_test_case  {  	public function get_formatted_filesize_test_data() diff --git a/tests/functions/get_preg_expression_test.php b/tests/functions/get_preg_expression_test.php index e74017d315..b8254b03ea 100644 --- a/tests/functions/get_preg_expression_test.php +++ b/tests/functions/get_preg_expression_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_functions_get_preg_expression_test extends phpbb_test_case  {  	public function data_path_remove_dot_trailing_slash() diff --git a/tests/functions/get_remote_file_test.php b/tests/functions/get_remote_file_test.php index 612d82273e..1550aa37e6 100644 --- a/tests/functions/get_remote_file_test.php +++ b/tests/functions/get_remote_file_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; -  /**  * @group slow  */ diff --git a/tests/functions/language_select_test.php b/tests/functions/language_select_test.php index 6762ead5a1..2d1296d72f 100644 --- a/tests/functions/language_select_test.php +++ b/tests/functions/language_select_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_functions_language_select_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/functions/make_clickable_email_test.php b/tests/functions/make_clickable_email_test.php index 4c802d0487..f32b4339a8 100644 --- a/tests/functions/make_clickable_email_test.php +++ b/tests/functions/make_clickable_email_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_functions_make_clickable_email_test extends phpbb_test_case  {  	protected function setUp() diff --git a/tests/functions/make_clickable_test.php b/tests/functions/make_clickable_test.php index 63beeb06b2..48fc2c19fb 100644 --- a/tests/functions/make_clickable_test.php +++ b/tests/functions/make_clickable_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_functions_make_clickable_test extends phpbb_test_case  {  	/** diff --git a/tests/functions/obtain_online_test.php b/tests/functions/obtain_online_test.php index e793a4eb82..778753e5d2 100644 --- a/tests/functions/obtain_online_test.php +++ b/tests/functions/obtain_online_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_functions_obtain_online_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/functions/parse_cfg_file_test.php b/tests/functions/parse_cfg_file_test.php index b47e25fbc1..017a931f28 100644 --- a/tests/functions/parse_cfg_file_test.php +++ b/tests/functions/parse_cfg_file_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_functions_parse_cfg_file extends phpbb_test_case  {  	public function parse_cfg_file_data() diff --git a/tests/functions/quoteattr_test.php b/tests/functions/quoteattr_test.php index 6e191f9610..dbad7a99d8 100644 --- a/tests/functions/quoteattr_test.php +++ b/tests/functions/quoteattr_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_quoteattr_test extends phpbb_test_case  {  	public function quoteattr_test_data() diff --git a/tests/functions/style_select_test.php b/tests/functions/style_select_test.php index a918f83155..27f0e68c88 100644 --- a/tests/functions/style_select_test.php +++ b/tests/functions/style_select_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_functions_style_select_test extends phpbb_database_test_case  {  	public function getDataSet() diff --git a/tests/functions/user_delete_test.php b/tests/functions/user_delete_test.php index c224323273..db9b6e0c90 100644 --- a/tests/functions/user_delete_test.php +++ b/tests/functions/user_delete_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';  class phpbb_functions_user_delete_test extends phpbb_database_test_case @@ -28,10 +27,12 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case  	{  		parent::setUp(); -		global $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user; +		global $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $phpbb_root_path, $phpEx;  		$this->db = $db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$phpbb_container = new phpbb_mock_container_builder();  		$config = new \phpbb\config\config(array( @@ -39,8 +40,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case  			'auth_oauth_google_key'	=> 'foo',  			'auth_oauth_google_secret'	=> 'bar',  		)); -		set_config_count('foobar', 0, false, $config); -		$cache = new \phpbb\cache\driver\null(); +		$cache = new \phpbb\cache\driver\dummy();  		$request = new phpbb_mock_request();  		$notification_manager = new phpbb_mock_notification_manager();  		$provider_collection =  new \phpbb\auth\provider_collection($phpbb_container, $config); @@ -67,6 +67,7 @@ class phpbb_functions_user_delete_test extends phpbb_database_test_case  			$request,  			$user,  			'phpbb_oauth_tokens', +			'phpbb_oauth_states',  			'phpbb_oauth_accounts',  			$oauth_provider_collection,  			'phpbb_users', diff --git a/tests/functions/validate_email_test.php b/tests/functions/validate_email_test.php index b46509fda7..7f8b2679d4 100644 --- a/tests/functions/validate_email_test.php +++ b/tests/functions/validate_email_test.php @@ -7,7 +7,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';  require_once dirname(__FILE__) . '/../mock/user.php';  require_once dirname(__FILE__) . '/validate_data_helper.php'; diff --git a/tests/functions/validate_password_test.php b/tests/functions/validate_password_test.php index c5942e79bf..5e34c8baba 100644 --- a/tests/functions/validate_password_test.php +++ b/tests/functions/validate_password_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';  require_once dirname(__FILE__) . '/validate_data_helper.php'; diff --git a/tests/functions/validate_string_test.php b/tests/functions/validate_string_test.php index 24026e4c9f..7aca14c334 100644 --- a/tests/functions/validate_string_test.php +++ b/tests/functions/validate_string_test.php @@ -12,7 +12,6 @@  */  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  require_once dirname(__FILE__) . '/validate_data_helper.php';  class phpbb_functions_validate_string_test extends phpbb_test_case diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php index 951d5794e6..8dcec88103 100644 --- a/tests/functions/validate_user_email_test.php +++ b/tests/functions/validate_user_email_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';  require_once dirname(__FILE__) . '/../mock/user.php';  require_once dirname(__FILE__) . '/validate_data_helper.php'; diff --git a/tests/functions/validate_username_test.php b/tests/functions/validate_username_test.php index 4fa5af7ff3..d310f58036 100644 --- a/tests/functions/validate_username_test.php +++ b/tests/functions/validate_username_test.php @@ -11,9 +11,7 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  require_once dirname(__FILE__) . '/../mock/cache.php';  require_once dirname(__FILE__) . '/validate_data_helper.php'; diff --git a/tests/functions_acp/validate_config_vars_test.php b/tests/functions_acp/validate_config_vars_test.php index 32738e4351..5c31888291 100644 --- a/tests/functions_acp/validate_config_vars_test.php +++ b/tests/functions_acp/validate_config_vars_test.php @@ -12,7 +12,6 @@  */  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  class phpbb_functions_acp_validate_config_vars_test extends phpbb_test_case  { diff --git a/tests/functions_acp/validate_range_test.php b/tests/functions_acp/validate_range_test.php index 6408e29a26..9e9154a43c 100644 --- a/tests/functions_acp/validate_range_test.php +++ b/tests/functions_acp/validate_range_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';  class phpbb_functions_acp_validate_range_test extends phpbb_test_case diff --git a/tests/functions_content/get_username_string_test.php b/tests/functions_content/get_username_string_test.php index 01ec97f6a4..e79342d05d 100644 --- a/tests/functions_content/get_username_string_test.php +++ b/tests/functions_content/get_username_string_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_functions_content_get_username_string_test extends phpbb_test_case  {  	public function setUp() diff --git a/tests/functions_content/phpbb_clean_search_string_test.php b/tests/functions_content/phpbb_clean_search_string_test.php index abd107097c..34ae0575c5 100644 --- a/tests/functions_content/phpbb_clean_search_string_test.php +++ b/tests/functions_content/phpbb_clean_search_string_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_functions_content_phpbb_clean_search_string_test extends phpbb_test_case  {  	public function phpbb_clean_search_string_data() diff --git a/tests/functions_install/ignore_new_file_on_update_test.php b/tests/functions_install/ignore_new_file_on_update_test.php deleted file mode 100644 index 822c5e6789..0000000000 --- a/tests/functions_install/ignore_new_file_on_update_test.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** -* -* This file is part of the phpBB Forum Software package. -* -* @copyright (c) phpBB Limited <https://www.phpbb.com> -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php'; - -class phpbb_functions_install_ignore_new_file_on_update_test extends phpbb_test_case -{ -	static public function ignore_new_file_on_update_data() -	{ -		return array( -			array('willneverexist.php', false), -			array('includes/dirwillneverexist/newfile.php', false), - -			array('language/en/email/short/bookmark.txt', false), -			array('language/languagewillneverexist/email/short/bookmark.txt', true), - -			array('styles/prosilver/template/bbcode.html', false), -			array('styles/stylewillneverexist/template/bbcode.html', true), - -			array('styles/prosilver/theme/en/icon_user_online.gif', false), -			array('styles/prosilver/theme/languagewillneverexist/icon_user_online.gif', true), - -			array('styles/prosilver/theme/imageset.css', false), -		); -	} - -	/** -	* @dataProvider ignore_new_file_on_update_data -	*/ -	public function test_ignore_new_file_on_update($file, $expected) -	{ -		global $phpbb_root_path; -		$this->assertEquals($expected, phpbb_ignore_new_file_on_update($phpbb_root_path, $file)); -	} -} diff --git a/tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml b/tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml new file mode 100644 index 0000000000..c78d63f7cb --- /dev/null +++ b/tests/functions_privmsgs/fixtures/get_max_setting_from_group.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_groups"> +		<column>group_id</column> +		<column>group_desc</column> +		<column>group_message_limit</column> +		<column>group_max_recipients</column> +		<row> +			<value>1</value> +			<value></value> +			<value>1</value> +			<value>3</value> +		</row> +		<row> +			<value>2</value> +			<value></value> +			<value>2</value> +			<value>4</value> +		</row> +		<row> +			<value>3</value> +			<value></value> +			<value>0</value> +			<value>0</value> +		</row> +		<row> +			<value>4</value> +			<value></value> +			<value>0</value> +			<value>5</value> +		</row> +	</table> +	<table name="phpbb_user_group"> +		<column>user_id</column> +		<column>group_id</column> +		<column>user_pending</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>0</value> +		</row> +		<row> +			<value>1</value> +			<value>2</value> +			<value>0</value> +		</row> +		<row> +			<value>1</value> +			<value>3</value> +			<value>0</value> +		</row> +		<row> +			<value>2</value> +			<value>1</value> +			<value>0</value> +		</row> +		<row> +			<value>2</value> +			<value>2</value> +			<value>0</value> +		</row> +		<row> +			<value>3</value> +			<value>3</value> +			<value>0</value> +		</row> +		<row> +			<value>4</value> +			<value>4</value> +			<value>0</value> +		</row> +		<row> +			<value>5</value> +			<value>3</value> +			<value>1</value> +		</row> +		<row> +			<value>5</value> +			<value>2</value> +			<value>0</value> +		</row> +	</table> +</dataset> diff --git a/tests/functions_privmsgs/get_max_setting_from_group_test.php b/tests/functions_privmsgs/get_max_setting_from_group_test.php new file mode 100644 index 0000000000..3eb7866802 --- /dev/null +++ b/tests/functions_privmsgs/get_max_setting_from_group_test.php @@ -0,0 +1,64 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_privmsgs.php'; + +class phpbb_functions_privmsgs_get_max_setting_from_group_test extends phpbb_database_test_case +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/get_max_setting_from_group.xml'); +	} + +	/** @var \phpbb\db\driver\driver_interface */ +	protected $db; + +	protected function setUp() +	{ +		parent::setUp(); + +		$this->db = $this->new_dbal(); +	} + +	static public function get_max_setting_from_group_data() +	{ +		return array( +			array(1, 0, 'message_limit'), +			array(2, 2, 'message_limit'), +			array(3, 0, 'message_limit'), +			array(4, 0, 'message_limit'), +			array(5, 2, 'message_limit'), +			array(1, 0, 'max_recipients'), +			array(2, 4, 'max_recipients'), +			array(3, 0, 'max_recipients'), +			array(4, 5, 'max_recipients'), +			array(5, 4, 'max_recipients'), +		); +	} + +	/** +	* @dataProvider get_max_setting_from_group_data +	*/ +	public function test_get_max_setting_from_group($user_id, $expected, $setting) +	{ +		$this->assertEquals($expected, phpbb_get_max_setting_from_group($this->db, $user_id, $setting)); +	} + +	/** +	 * @expectedException InvalidArgumentException +	 */ +	public function test_get_max_setting_from_group_throws() +	{ +		phpbb_get_max_setting_from_group($this->db, ANONYMOUS, 'not_a_setting'); +	} +} diff --git a/tests/functions_user/delete_user_test.php b/tests/functions_user/delete_user_test.php index 7db69e332c..25042d9f1b 100644 --- a/tests/functions_user/delete_user_test.php +++ b/tests/functions_user/delete_user_test.php @@ -7,9 +7,7 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  class phpbb_functions_user_delete_user_test extends phpbb_database_test_case  { @@ -25,19 +23,19 @@ class phpbb_functions_user_delete_user_test extends phpbb_database_test_case  	{  		parent::setUp(); -		global $cache, $config, $db, $phpbb_dispatcher, $phpbb_container; +		global $cache, $config, $db, $phpbb_dispatcher, $phpbb_container, $phpbb_root_path;  		$db = $this->db = $this->new_dbal();  		$config = new \phpbb\config\config(array(  			'load_online_time'	=> 5,  			'search_type'		=> '\phpbb\search\fulltext_mysql',  		)); -		set_config(false, false, false, $config); -		set_config_count(false, false, false, $config);  		$cache = new phpbb_mock_null_cache();  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$phpbb_container = new phpbb_mock_container_builder();  		$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); +		// Works as a workaround for tests +		$phpbb_container->set('attachment.manager', new \phpbb\attachment\delete($config, $db, new \phpbb_mock_event_dispatcher(), new \phpbb\filesystem\filesystem(), new \phpbb\attachment\resync($db), $phpbb_root_path));  		$phpbb_container->set(  			'auth.provider.db',  			new phpbb_mock_auth_provider() diff --git a/tests/functions_user/group_user_attributes_test.php b/tests/functions_user/group_user_attributes_test.php index 99a15b32bf..3124d57ba0 100644 --- a/tests/functions_user/group_user_attributes_test.php +++ b/tests/functions_user/group_user_attributes_test.php @@ -11,9 +11,7 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  class phpbb_functions_user_group_user_attributes_test extends phpbb_database_test_case  { @@ -139,7 +137,7 @@ class phpbb_functions_user_group_user_attributes_test extends phpbb_database_tes  		$auth = $this->getMock('\phpbb\auth\auth');  		$auth->expects($this->any())  			->method('acl_clear_prefetch'); -		$cache_driver = new \phpbb\cache\driver\null(); +		$cache_driver = new \phpbb\cache\driver\dummy();  		$phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');  		$phpbb_container  			->expects($this->any()) diff --git a/tests/group/helper_test.php b/tests/group/helper_test.php new file mode 100644 index 0000000000..2377a6f47c --- /dev/null +++ b/tests/group/helper_test.php @@ -0,0 +1,68 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_group_helper_test extends phpbb_test_case +{ +	/** @var  \phpbb\group\helper */ +	protected $group_helper; + +	public function setUp() +	{ +		global $phpbb_root_path, $phpEx; + +		// Set up language service +		$lang = new \phpbb\language\language( +			new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx) +		); + +		// Set up language data for testing +		$reflection_class = new ReflectionClass('\phpbb\language\language'); + +		// Set default language files loaded flag to true +		$loaded_flag = $reflection_class->getProperty('common_language_files_loaded'); +		$loaded_flag->setAccessible(true); +		$loaded_flag->setValue($lang, true); + +		// Set up test language data +		$lang_array = $reflection_class->getProperty('lang'); +		$lang_array->setAccessible(true); +		$lang_array->setValue($lang, $this->get_test_language_data_set()); + +		// Set up group helper +		$this->group_helper = new \phpbb\group\helper($lang); +	} + +	public function test_get_name() +	{ +		// They should be totally fine +		$this->assertEquals('Bots', $this->group_helper->get_name('Bots')); +		$this->assertEquals('Some new group', $this->group_helper->get_name('new_group')); +		$this->assertEquals('Should work', $this->group_helper->get_name('group_with_ümlauts')); + +		// This should fail (obviously) +		$this->assertNotEquals('They key does not contain uppercase letters', $this->group_helper->get_name('not_uppercase')); + +		// The key doesn't exist so just return group name... +		$this->assertEquals('Awesome group', $this->group_helper->get_name('Awesome group')); +	} + +	protected function get_test_language_data_set() +	{ +		return array( +			'G_BOTS'					=> 'Bots', +			'G_NEW_GROUP'				=> 'Some new group', +			'G_not_uppercase'			=> 'The key does not contain uppercase letters', +			'G_GROUP_WITH_ÜMLAUTS'		=> 'Should work', +		); +	} +} diff --git a/tests/groupposition/legend_test.php b/tests/groupposition/legend_test.php index fe003e93a7..02ddb7cbce 100644 --- a/tests/groupposition/legend_test.php +++ b/tests/groupposition/legend_test.php @@ -11,7 +11,6 @@  *  */ -  class phpbb_groupposition_legend_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -33,11 +32,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	*/  	public function test_get_group_value($group_id, $expected, $throws_exception)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		if ($throws_exception) @@ -51,11 +52,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	public function test_get_group_count()  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\legend($db, $user); @@ -91,11 +94,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	*/  	public function test_add_group($group_id, $expected_added, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\legend($db, $user); @@ -179,11 +184,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	*/  	public function test_delete_group($group_id, $skip_group, $expected_deleted, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\legend($db, $user); @@ -234,11 +241,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	*/  	public function test_move_up($group_id, $excepted_moved, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\legend($db, $user); @@ -289,11 +298,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	*/  	public function test_move_down($group_id, $excepted_moved, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\legend($db, $user); @@ -387,11 +398,13 @@ class phpbb_groupposition_legend_test extends phpbb_database_test_case  	*/  	public function test_move($group_id, $increment, $excepted_moved, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\legend($db, $user); diff --git a/tests/groupposition/teampage_test.php b/tests/groupposition/teampage_test.php index 1e61e3ebfb..3b916670f7 100644 --- a/tests/groupposition/teampage_test.php +++ b/tests/groupposition/teampage_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_groupposition_teampage_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -35,11 +32,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_get_group_value($group_id, $expected, $throws_exception)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		if ($throws_exception) @@ -53,11 +52,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	public function test_get_group_count()  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -137,11 +138,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_add_group_teampage($group_id, $parent_id, $expected_added, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -180,11 +183,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_add_category_teampage($group_name, $expected_added, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -247,11 +252,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_delete_group($group_id, $expected_deleted, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -299,11 +306,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_delete_teampage($teampage_id, $expected_deleted, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -462,11 +471,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_move($group_id, $move_delta, $excepted_moved, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); @@ -625,11 +636,13 @@ class phpbb_groupposition_teampage_test extends phpbb_database_test_case  	*/  	public function test_move_teampage($teampage_id, $move_delta, $excepted_moved, $expected)  	{ -		global $cache; +		global $cache, $phpbb_root_path, $phpEx;  		$cache = new phpbb_mock_cache;  		$db = $this->new_dbal(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = array();  		$test_class = new \phpbb\groupposition\teampage($db, $user, $cache); diff --git a/tests/help/manager_test.php b/tests/help/manager_test.php new file mode 100644 index 0000000000..68534d9a32 --- /dev/null +++ b/tests/help/manager_test.php @@ -0,0 +1,184 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_help_manager_test extends phpbb_test_case +{ +	/** @var \phpbb\help\manager */ +	protected $manager; +	/** @var \phpbb\template\template */ +	protected $template; +	/** @var \phpbb\language\language */ +	protected $language; + +	public function setUp() +	{ +		$this->template = $this->getMockBuilder('\phpbb\template\template') +			->disableOriginalConstructor() +			->getMock(); +		$this->language = $this->getMockBuilder('\phpbb\language\language') +			->disableOriginalConstructor() +			->getMock(); + +		$this->manager = new \phpbb\help\manager( +			new \phpbb_mock_event_dispatcher(), +			$this->language, +			$this->template +		); +	} + +	public function add_block_data() +	{ +		return array( +			array('abc', false, array(), false), +			array('def', true, array(), true), +			array( +				'abc', +				false, +				array( +					'question1' => 'answer1', +					'question2' => 'answer2', +					'question3' => 'answer3', +				), +				false +			), +		); +	} + +	/** +	 * @dataProvider add_block_data +	 * +	 * @param string $block_name +	 * @param bool $switch +	 * @param array $questions +	 * @param bool $switch_expected +	 */ +	public function test_add_block($block_name, $switch, $questions, $switch_expected) +	{ +		$this->language->expects($this->at(0)) +			->method('lang') +			->with($block_name) +			->willReturn(strtoupper($block_name)); +		$lang_call_count = 1; +		foreach ($questions as $question => $answer) +		{ +			$this->language->expects($this->at($lang_call_count)) +				->method('lang') +				->with($question) +				->willReturn(strtoupper($question)); +			$lang_call_count++; + +			$this->language->expects($this->at($lang_call_count)) +				->method('lang') +				->with($answer) +				->willReturn(strtoupper($answer)); +			$lang_call_count++; +		} + +		$this->template->expects($this->at(0)) +			->method('assign_block_vars') +			->with('faq_block', array( +				'BLOCK_TITLE' => strtoupper($block_name), +				'SWITCH_COLUMN' => $switch_expected, +			)); +		$template_call_count = 1; +		foreach ($questions as $question => $answer) +		{ +			$this->template->expects($this->at($template_call_count)) +				->method('assign_block_vars') +				->with('faq_block.faq_row', array( +					'FAQ_QUESTION' => strtoupper($question), +					'FAQ_ANSWER' => strtoupper($answer), +				)); +			$template_call_count++; +		} + +		$this->manager->add_block($block_name, $switch, $questions); + +		$this->assertEquals($switch_expected, $this->manager->switched_column()); +	} + +	public function add_question_data() +	{ +		return array( +			array('abc', false, false), +			array('def', true, true), +		); +	} + +	/** +	 * @dataProvider add_question_data +	 * +	 * @param string $question +	 * @param string $answer +	 */ +	public function test_add_question($question, $answer) +	{ +		$this->language->expects($this->at(0)) +			->method('lang') +			->with($question) +			->willReturn(strtoupper($question)); +		$this->language->expects($this->at(1)) +			->method('lang') +			->with($answer) +			->willReturn(strtoupper($answer)); + +		$this->template->expects($this->once()) +			->method('assign_block_vars') +			->with('faq_block.faq_row', array( +				'FAQ_QUESTION' => strtoupper($question), +				'FAQ_ANSWER' => strtoupper($answer), +			)); + +		$this->manager->add_question($question, $answer); +	} + +	public function test_add_block_double_switch() +	{ +		$block_name = 'abc'; +		$switch_expected = true; + +		$this->language->expects($this->at(0)) +			->method('lang') +			->with($block_name) +			->willReturn(strtoupper($block_name)); + +		$this->template->expects($this->at(0)) +			->method('assign_block_vars') +			->with('faq_block', array( +				'BLOCK_TITLE' => strtoupper($block_name), +				'SWITCH_COLUMN' => $switch_expected, +			)); + +		$this->manager->add_block($block_name, true); +		$this->assertTrue($this->manager->switched_column()); + +		// Add a second block with switch +		$block_name = 'def'; +		$switch_expected = false; + +		$this->language->expects($this->at(0)) +			->method('lang') +			->with($block_name) +			->willReturn(strtoupper($block_name)); + +		$this->template->expects($this->at(0)) +			->method('assign_block_vars') +			->with('faq_block', array( +				'BLOCK_TITLE' => strtoupper($block_name), +				'SWITCH_COLUMN' => $switch_expected, +			)); + +		$this->manager->add_block($block_name, true); +		$this->assertTrue($this->manager->switched_column()); +	} +} diff --git a/tests/installer/database_helper_test.php b/tests/installer/database_helper_test.php new file mode 100644 index 0000000000..ed355884f6 --- /dev/null +++ b/tests/installer/database_helper_test.php @@ -0,0 +1,157 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_installer_database_helper_test extends phpbb_test_case +{ +	/** +	 * @var phpbb\install\helper\database +	 */ +	private $database_helper; + +	public function setUp() +	{ +		$filesystem = new \phpbb\filesystem\filesystem(); +		$phpbb_root_path = ''; +		$this->database_helper = new \phpbb\install\helper\database($filesystem, $phpbb_root_path); +	} + +	/** +	 * @param string	$input +	 * @param string	$expected +	 * +	 * @dataProvider	comment_string_provider +	 */ +	public function test_remove_comments($input, $expected) +	{ +		$this->assertEquals($expected, $this->database_helper->remove_comments($input)); +	} + +	/** +	 * @param array		$expected +	 * @param string	$sql +	 * @param string	$delimiter +	 * +	 * @dataProvider	sql_file_string_provider +	 */ +	public function test_split_sql($expected, $sql, $delimiter) +	{ +		$this->assertEquals($expected, $this->database_helper->split_sql_file($sql, $delimiter)); +	} + +	/** +	 * @param bool|array	$expected +	 * @param string		$test_string +	 * +	 * @dataProvider	prefix_test_case_provider +	 */ +	public function test_validate_table_prefix($expected, $test_string) +	{ +		$db_helper_mock = $this->getMockBuilder('\phpbb\install\helper\database') +			->setMethods(array('get_available_dbms')) +			->disableOriginalConstructor() +			->getMock(); + +		$db_helper_mock->method('get_available_dbms') +			->willReturn(array('sqlite3' => array( +				'LABEL'			=> 'SQLite3', +				'SCHEMA'		=> 'sqlite', +				'MODULE'		=> 'sqlite3', +				'DELIM'			=> ';', +				'DRIVER'		=> 'phpbb\db\driver\sqlite3', +				'AVAILABLE'		=> true, +				'2.0.x'			=> false, +			))); + +		$this->assertEquals($expected, $db_helper_mock->validate_table_prefix('sqlite3', $test_string)); +	} + +	// Data provider for the remove comments function +	public function comment_string_provider() +	{ +		return array( +			array( +				'abc', +				'abc', +			), +			array( +				'abc /* asdf */', +				"abc \n", +			), +			array( +				'abc /* asdf */ f', +				"abc \n f", +			), +			array( +				'# abc', +				"\n", +			), +		); +	} + +	// Data provider for the sql file splitter function +	public function sql_file_string_provider() +	{ +		return array( +			array( +				array( +					'abcd "efgh"' . "\n" . 'qwerty', +					'SELECT * FROM table', +				), +				'abcd "efgh"' . "\n" . +				'qwerty;' . "\n" . +				'SELECT * FROM table', +				';', +			), +		); +	} + +	// Test data for prefix test +	public function prefix_test_case_provider() +	{ +		return array( +			array( +				true, +				'phpbb_', +			), +			array( +				true, +				'phpbb', +			), +			array( +				array( +					array('title' => 'INST_ERR_DB_INVALID_PREFIX'), +				), +				'1hpbb_', +			), +			array( +				array( +					array('title' => 'INST_ERR_DB_INVALID_PREFIX'), +				), +				'?hpbb_', +			), +			array( +				array( +					array('title' => array('INST_ERR_PREFIX_TOO_LONG', 200)), +				), +				'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', +			), +			array( +				array( +					array('title' => 'INST_ERR_DB_INVALID_PREFIX'), +					array('title' => array('INST_ERR_PREFIX_TOO_LONG', 200)), +				), +				'_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', +			), +		); +	} +} diff --git a/tests/installer/installer_config_test.php b/tests/installer/installer_config_test.php new file mode 100644 index 0000000000..13ac325a79 --- /dev/null +++ b/tests/installer/installer_config_test.php @@ -0,0 +1,80 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +use phpbb\install\helper\config; + +class phpbb_installer_config_test extends phpbb_test_case +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	private $config; + +	public function setUp() +	{ +		$phpbb_root_path = __DIR__ . './../../phpBB/'; +		$filesystem = $this->getMock('\phpbb\filesystem\filesystem'); +		$php_ini = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper') +			->getMock(); +		$php_ini->method('getInt') +			->willReturn(-1); +		$php_ini->method('getBytes') +			->willReturn(-1); + +		$this->config = new config($filesystem, $php_ini, $phpbb_root_path); +	} + +	public function test_set_get_var() +	{ +		$this->config->set('foo', 'bar'); +		$this->assertEquals('bar', $this->config->get('foo')); +	} + +	public function test_get_time_remaining() +	{ +		$this->assertGreaterThan(0, $this->config->get_time_remaining()); +	} + +	public function test_get_memory_remaining() +	{ +		$this->assertGreaterThan(0, $this->config->get_memory_remaining()); +	} + +	public function test_progress_tracking() +	{ +		$this->config->set_finished_task(0); +		$this->config->set_active_module('bar', 5); +		$this->config->set_task_progress_count(10); +		$this->config->increment_current_task_progress(); + +		$progress_data = $this->config->get_progress_data(); +		$this->assertEquals(1, $progress_data['current_task_progress']); + +		$this->config->increment_current_task_progress(2); + +		// We only want to check these values +		$result = $this->config->get_progress_data(); +		$expected_result = array( +			'last_task_module_name'		=> 'bar', +			'last_task_module_index'	=> 5, +			'last_task_index'			=> 0, +			'max_task_progress'			=> 10, +			'current_task_progress'		=> 3, +		); + +		foreach ($expected_result as $key => $value) +		{ +			$this->assertEquals($value, $result[$key]); +		} +	} +} diff --git a/tests/installer/mocks/test_installer_module.php b/tests/installer/mocks/test_installer_module.php new file mode 100644 index 0000000000..e6ebbba263 --- /dev/null +++ b/tests/installer/mocks/test_installer_module.php @@ -0,0 +1,20 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class test_installer_module extends \phpbb\install\module_base +{ +	public function get_navigation_stage_path() +	{ +		return array(); +	} +} diff --git a/tests/installer/mocks/test_installer_task_mock.php b/tests/installer/mocks/test_installer_task_mock.php new file mode 100644 index 0000000000..ccd62b3bf4 --- /dev/null +++ b/tests/installer/mocks/test_installer_task_mock.php @@ -0,0 +1,44 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class test_installer_task_mock extends \phpbb\install\task_base +{ +	private $task_was_runned; + +	public function __construct() +	{ +		$this->task_was_runned = false; + +		parent::__construct(); +	} + +	public function run() +	{ +		$this->task_was_runned = true; +	} + +	public function was_task_runned() +	{ +		return $this->task_was_runned; +	} + +	public function get_task_lang_name() +	{ +		return ''; +	} + +	public static function get_step_count() +	{ +		return 2; +	} +} diff --git a/tests/installer/module_base_test.php b/tests/installer/module_base_test.php new file mode 100644 index 0000000000..9578010047 --- /dev/null +++ b/tests/installer/module_base_test.php @@ -0,0 +1,65 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +require_once __DIR__ . '/mocks/test_installer_task_mock.php'; +require_once __DIR__ . '/mocks/test_installer_module.php'; + +class module_base_test extends phpbb_test_case +{ +	/** +	 * @var \phpbb\install\module_interface +	 */ +	protected $module; + +	/** +	 * @var phpbb_mock_container_builder +	 */ +	protected $container; + +	public function setUp() +	{ +		// DI container mock +		$this->container = new phpbb_mock_container_builder(); +		$this->container->set('task_one', new test_installer_task_mock()); +		$this->container->set('task_two', new test_installer_task_mock()); + +		// the collection +		$module_collection = new \phpbb\di\ordered_service_collection($this->container); +		$module_collection->add('task_one'); +		$module_collection->add('task_two'); +		$module_collection->add_service_class('task_one', 'test_installer_task_mock'); +		$module_collection->add_service_class('task_two', 'test_installer_task_mock'); + +		$this->module = new test_installer_module($module_collection, true, false); + +		$iohandler = $this->getMock('\phpbb\install\helper\iohandler\iohandler_interface'); +		$config = new \phpbb\install\helper\config(new \phpbb\filesystem\filesystem(), new \bantu\IniGetWrapper\IniGetWrapper(), '', 'php'); +		$this->module->setup($config, $iohandler); +	} + +	public function test_run() +	{ +		$this->module->run(); + +		$task = $this->container->get('task_one'); +		$this->assertTrue($task->was_task_runned()); + +		$task = $this->container->get('task_two'); +		$this->assertTrue($task->was_task_runned()); +	} + +	public function test_step_count() +	{ +		$this->assertEquals(4, $this->module->get_step_count()); +	} +} diff --git a/tests/installer/navigation_provider_test.php b/tests/installer/navigation_provider_test.php new file mode 100644 index 0000000000..ea39af66cd --- /dev/null +++ b/tests/installer/navigation_provider_test.php @@ -0,0 +1,34 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_installer_navigation_provider_test extends phpbb_test_case +{ +	public function test_navigation() +	{ +		// Mock nav interface +		$nav_stub = $this->getMockBuilder('\phpbb\install\helper\navigation\navigation_interface') +			->getMock(); +		$nav_stub->method('get') +			->willReturn(array('foo' => 'bar')); + +		// Set up dependencies +		$container = new phpbb_mock_container_builder(); +		$container->set('foo', $nav_stub); +		$nav_collection = new \phpbb\di\service_collection($container); +		$nav_collection->add('foo'); + +		// Let's test +		$nav_provider = new \phpbb\install\helper\navigation\navigation_provider($nav_collection); +		$this->assertEquals(array('foo' => 'bar'), $nav_provider->get()); +	} +} diff --git a/tests/language/language_test.php b/tests/language/language_test.php new file mode 100644 index 0000000000..29b4873dcb --- /dev/null +++ b/tests/language/language_test.php @@ -0,0 +1,243 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_language_test extends phpbb_test_case +{ +	/** @var \phpbb\language\language */ +	protected $lang; + +	public function setUp() +	{ +		global $phpbb_root_path, $phpEx; + +		// Set up language service +		$this->lang = new \phpbb\language\language( +			new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx) +		); + +		// Set up language data for testing +		$reflection_class = new ReflectionClass('\phpbb\language\language'); + +		// Set default language files loaded flag to true +		$loaded_flag = $reflection_class->getProperty('common_language_files_loaded'); +		$loaded_flag->setAccessible(true); +		$loaded_flag->setValue($this->lang, true); + +		// Set up test language data +		$lang_array = $reflection_class->getProperty('lang'); +		$lang_array->setAccessible(true); +		$lang_array->setValue($this->lang, $this->get_test_data_set()); +	} + +	public function test_is_set() +	{ +		// Check for non-existing key +		$this->assertFalse($this->lang->is_set('VALUE')); +		$this->assertFalse($this->lang->is_set(array('dateformat', 'MAYBE'))); + +		// Check for existing key +		$this->assertTrue($this->lang->is_set('FOO')); +		$this->assertTrue($this->lang->is_set(array('dateformat', 'AGO'))); + +		// Array doesn't exist at all... +		$this->assertFalse($this->lang->is_set(array('PHPBB', 'PHP'))); +	} + +	public function test_lang_raw() +	{ +		$this->assertEquals($this->lang->lang_raw('FOO'), 'BAR'); +		$this->assertEquals($this->lang->lang_raw('VOID'), 'VOID'); +		$this->assertEquals($this->lang->lang_raw('ARRY'), array( +			0		=> 'No posts',		// 0 +			1		=> '1 post',		// 1 +			2		=> '%d posts',		// 2+ +		)); +	} + +	public function test_lang_array() +	{ +		$this->assertEquals($this->lang->lang_array('FOO'), 'BAR'); +		$this->assertEquals($this->lang->lang_array('VOID'), 'VOID'); +		$this->assertEquals($this->lang->lang_array('ARRY', [0]), 'No posts'); +		$this->assertEquals($this->lang->lang_array('FOO', [2, 3, 'BARZ']), 'BAR'); +	} + +	public function test_lang() +	{ +		// No param +		$this->assertEquals($this->lang->lang('FOO'), 'BAR'); +		$this->assertEquals($this->lang->lang('EMPTY'), ''); +		$this->assertEquals($this->lang->lang('ZERO'), '0'); + +		// Invalid index +		$this->assertEquals($this->lang->lang('VOID'), 'VOID'); + +		// Unnecessary param +		$this->assertEquals($this->lang->lang('FOO', 2), 'BAR'); +		$this->assertEquals($this->lang->lang('FOO', 2, 3), 'BAR'); +		$this->assertEquals($this->lang->lang('FOO', 2, 3, 'BARZ'), 'BAR'); + +		// String +		$this->assertEquals($this->lang->lang('STR', 24, 'x', 42), '24 x, 42 topics'); +		$this->assertEquals($this->lang->lang('STR2', 64), '64 foos'); + +		// Array +		$this->assertEquals($this->lang->lang('ARRY', 0), 'No posts'); +		$this->assertEquals($this->lang->lang('ARRY', 1), '1 post'); +		$this->assertEquals($this->lang->lang('ARRY', 2), '2 posts'); +		$this->assertEquals($this->lang->lang('ARRY', 123), '123 posts'); + +		// Empty array returns the language key +		$this->assertEquals($this->lang->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY'); + +		// No 0 key defined +		$this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 0), '0 posts'); +		$this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 1), '1 post'); +		$this->assertEquals($this->lang->lang('ARRY_NO_ZERO', 2), '2 posts'); + +		// Array with missing keys +		$this->assertEquals($this->lang->lang('ARRY_MISSING', 2), '2 post'); + +		// Floats as array key +		$this->assertEquals($this->lang->lang('ARRY_FLOAT', 1.3), '1 post'); +		$this->assertEquals($this->lang->lang('ARRY_FLOAT', 2.0), '2.0 posts'); +		$this->assertEquals($this->lang->lang('ARRY_FLOAT', 2.51), '2.5 posts'); + +		// Use sub key, if first paramenter is an array +		$this->assertEquals($this->lang->lang(array('dateformat', 'AGO'), 2), '2 seconds'); + +		// ticket PHPBB3-9949 - use first int to determinate the plural-form to use +		$this->assertEquals($this->lang->lang('ARRY', 1, 2), '1 post'); +		$this->assertEquals($this->lang->lang('ARRY', 1, 's', 2), '1 post'); +	} + +	public function test_lang_plural_rules() +	{ +		$this->assertEquals($this->lang->lang('PLURAL_ARRY', 0), '0 is 0'); +		$this->assertEquals($this->lang->lang('PLURAL_ARRY', 1), '1 is 1'); +		$this->assertEquals($this->lang->lang('PLURAL_ARRY', 103), '103 ends with 01-10'); +		$this->assertEquals($this->lang->lang('PLURAL_ARRY', 15), '15 ends with 11-19'); +		$this->assertEquals($this->lang->lang('PLURAL_ARRY', 300), '300 is part of the last rule'); +	} + +	public function test_lang_bc() +	{ +		$user = new \phpbb\user($this->lang, '\phpbb\datetime'); + +		// Test lang array access +		$this->assertEquals($user->lang['FOO'], 'BAR'); + +		// No param +		$this->assertEquals($user->lang('FOO'), 'BAR'); +		$this->assertEquals($user->lang('EMPTY'), ''); +		$this->assertEquals($user->lang('ZERO'), '0'); + +		// Invalid index +		$this->assertEquals($user->lang('VOID'), 'VOID'); + +		// Unnecessary param +		$this->assertEquals($user->lang('FOO', 2), 'BAR'); +		$this->assertEquals($user->lang('FOO', 2, 3), 'BAR'); +		$this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR'); + +		// String +		$this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics'); +		$this->assertEquals($user->lang('STR2', 64), '64 foos'); + +		// Array +		$this->assertEquals($user->lang('ARRY', 0), 'No posts'); +		$this->assertEquals($user->lang('ARRY', 1), '1 post'); +		$this->assertEquals($user->lang('ARRY', 2), '2 posts'); +		$this->assertEquals($user->lang('ARRY', 123), '123 posts'); + +		// Empty array returns the language key +		$this->assertEquals($user->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY'); + +		// No 0 key defined +		$this->assertEquals($user->lang('ARRY_NO_ZERO', 0), '0 posts'); +		$this->assertEquals($user->lang('ARRY_NO_ZERO', 1), '1 post'); +		$this->assertEquals($user->lang('ARRY_NO_ZERO', 2), '2 posts'); + +		// Array with missing keys +		$this->assertEquals($user->lang('ARRY_MISSING', 2), '2 post'); + +		// Floats as array key +		$this->assertEquals($user->lang('ARRY_FLOAT', 1.3), '1 post'); +		$this->assertEquals($user->lang('ARRY_FLOAT', 2.0), '2.0 posts'); +		$this->assertEquals($user->lang('ARRY_FLOAT', 2.51), '2.5 posts'); + +		// Use sub key, if first paramenter is an array +		$this->assertEquals($user->lang(array('dateformat', 'AGO'), 2), '2 seconds'); + +		// ticket PHPBB3-9949 - use first int to determinate the plural-form to use +		$this->assertEquals($user->lang('ARRY', 1, 2), '1 post'); +		$this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post'); +	} + +	public function test_lang_plural_rules_bc() +	{ +		$user = new \phpbb\user($this->lang, '\phpbb\datetime'); + +		// ticket PHPBB3-10345 - different plural rules, not just 0/1/2+ +		$this->assertEquals($user->lang('PLURAL_ARRY', 0), '0 is 0'); +		$this->assertEquals($user->lang('PLURAL_ARRY', 1), '1 is 1'); +		$this->assertEquals($user->lang('PLURAL_ARRY', 103), '103 ends with 01-10'); +		$this->assertEquals($user->lang('PLURAL_ARRY', 15), '15 ends with 11-19'); +		$this->assertEquals($user->lang('PLURAL_ARRY', 300), '300 is part of the last rule'); +	} + +	protected function get_test_data_set() +	{ +		return array( +			'FOO'		=> 'BAR', +			'BARZ'		=> 'PENG', +			'EMPTY'		=> '', +			'ZERO'		=> '0', +			'STR'		=> '%d %s, %d topics', +			'STR2'		=> '%d foos', +			'ARRY'		=> array( +				0		=> 'No posts',		// 0 +				1		=> '1 post',		// 1 +				2		=> '%d posts',		// 2+ +			), +			'ARRY_NO_ZERO'	=> array( +				1		=> '1 post',		// 1 +				2		=> '%d posts',		// 0, 2+ +			), +			'ARRY_MISSING'	=> array( +				1		=> '%d post',		// 1 +				//Missing second plural +			), +			'ARRY_FLOAT'	=> array( +				1		=> '1 post',		// 1.x +				2		=> '%1$.1f posts',	// 0.x, 2+.x +			), +			'ARRY_EMPTY'	=> array( +			), +			'dateformat'	=> array( +				'AGO'	=> array( +					1	=> '%d second', +					2	=> '%d seconds', +				), +			), +			'PLURAL_RULE' => 13, +			'PLURAL_ARRY' => array( +				0		=> '%d is 0',						// 0 +				1		=> '%d is 1',						// 1 +				2		=> '%d ends with 01-10',			// ending with 01-10 +				3		=> '%d ends with 11-19',			// ending with 11-19 +				4		=> '%d is part of the last rule',	// everything else +			), +		); +	} +} diff --git a/tests/lock/db_test.php b/tests/lock/db_test.php index 6fc813cb38..5fbfa26554 100644 --- a/tests/lock/db_test.php +++ b/tests/lock/db_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_lock_db_test extends phpbb_database_test_case  {  	private $db; @@ -30,7 +28,6 @@ class phpbb_lock_db_test extends phpbb_database_test_case  		$db = $this->db = $this->new_dbal();  		$config = $this->config = new \phpbb\config\config(array('rand_seed' => '', 'rand_seed_last_update' => '0')); -		set_config(null, null, null, $this->config);  		$this->lock = new \phpbb\lock\db('test_lock', $this->config, $this->db);  	} diff --git a/tests/log/add_test.php b/tests/log/add_test.php index 29d3adaeb6..604c8364dc 100644 --- a/tests/log/add_test.php +++ b/tests/log/add_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_log_add_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -27,7 +25,9 @@ class phpbb_log_add_test extends phpbb_database_test_case  		$db = $this->new_dbal();  		$cache = new phpbb_mock_cache;  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$auth = $this->getMock('\phpbb\auth\auth');  		$log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); @@ -56,7 +56,9 @@ class phpbb_log_add_test extends phpbb_database_test_case  		$db = $this->new_dbal();  		$cache = new phpbb_mock_cache;  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$auth = $this->getMock('\phpbb\auth\auth');  		$log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); diff --git a/tests/log/delete_test.php b/tests/log/delete_test.php index ec43182a0c..e8b75d01d9 100644 --- a/tests/log/delete_test.php +++ b/tests/log/delete_test.php @@ -11,10 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_log_delete_test extends phpbb_database_test_case  {  	protected $log; @@ -30,7 +26,9 @@ class phpbb_log_delete_test extends phpbb_database_test_case  		$db = $this->new_dbal();  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->data['user_id'] = 1;  		$auth = $this->getMock('\phpbb\auth\auth'); diff --git a/tests/log/fixtures/delete_log.xml b/tests/log/fixtures/delete_log.xml index 4b2402102e..393c686f0c 100644 --- a/tests/log/fixtures/delete_log.xml +++ b/tests/log/fixtures/delete_log.xml @@ -6,6 +6,7 @@  		<column>user_id</column>  		<column>forum_id</column>  		<column>topic_id</column> +		<column>post_id</column>  		<column>reportee_id</column>  		<column>log_ip</column>  		<column>log_time</column> @@ -18,6 +19,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_INSTALL_INSTALLED</value> @@ -30,6 +32,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_KEY_NOT_EXISTS</value> @@ -42,6 +45,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_CRITICAL</value> @@ -54,6 +58,7 @@  			<value>12</value>  			<value>34</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD</value> @@ -66,6 +71,7 @@  			<value>12</value>  			<value>45</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD</value> @@ -78,6 +84,7 @@  			<value>23</value>  			<value>56</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD</value> @@ -90,6 +97,7 @@  			<value>12</value>  			<value>45</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD2</value> @@ -101,6 +109,7 @@  			<value>1</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>2</value>  			<value>127.0.0.1</value>  			<value>1</value> @@ -113,6 +122,7 @@  			<value>1</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>1</value>  			<value>127.0.0.1</value>  			<value>1</value> @@ -126,6 +136,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_SINGULAR_PLURAL</value> @@ -138,6 +149,7 @@  			<value>15</value>  			<value>3</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD3</value> @@ -150,6 +162,7 @@  			<value>13</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value></value> @@ -162,6 +175,7 @@  			<value>14</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value></value> @@ -174,6 +188,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value></value> @@ -186,6 +201,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value></value> diff --git a/tests/log/fixtures/empty_log.xml b/tests/log/fixtures/empty_log.xml index 261b6a622a..47fd639b17 100644 --- a/tests/log/fixtures/empty_log.xml +++ b/tests/log/fixtures/empty_log.xml @@ -6,6 +6,7 @@  		<column>user_id</column>  		<column>forum_id</column>  		<column>topic_id</column> +		<column>post_id</column>  		<column>reportee_id</column>  		<column>log_ip</column>  		<column>log_time</column> diff --git a/tests/log/fixtures/full_log.xml b/tests/log/fixtures/full_log.xml index ef35884444..5b9ded9ffb 100644 --- a/tests/log/fixtures/full_log.xml +++ b/tests/log/fixtures/full_log.xml @@ -6,6 +6,7 @@  		<column>user_id</column>  		<column>forum_id</column>  		<column>topic_id</column> +		<column>post_id</column>  		<column>reportee_id</column>  		<column>log_ip</column>  		<column>log_time</column> @@ -18,6 +19,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_INSTALL_INSTALLED</value> @@ -30,6 +32,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_KEY_NOT_EXISTS</value> @@ -42,6 +45,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_CRITICAL</value> @@ -54,6 +58,7 @@  			<value>12</value>  			<value>34</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD</value> @@ -66,6 +71,7 @@  			<value>12</value>  			<value>45</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD</value> @@ -78,6 +84,7 @@  			<value>23</value>  			<value>56</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD</value> @@ -90,6 +97,7 @@  			<value>12</value>  			<value>45</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD2</value> @@ -101,6 +109,7 @@  			<value>1</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>2</value>  			<value>127.0.0.1</value>  			<value>1</value> @@ -113,6 +122,7 @@  			<value>1</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>1</value>  			<value>127.0.0.1</value>  			<value>1</value> @@ -126,6 +136,7 @@  			<value>0</value>  			<value>0</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_SINGULAR_PLURAL</value> @@ -138,6 +149,7 @@  			<value>15</value>  			<value>3</value>  			<value>0</value> +			<value>0</value>  			<value>127.0.0.1</value>  			<value>1</value>  			<value>LOG_MOD3</value> diff --git a/tests/log/function_add_log_test.php b/tests/log/function_add_log_test.php index 63e468498e..3b5537fc13 100644 --- a/tests/log/function_add_log_test.php +++ b/tests/log/function_add_log_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_log_function_add_log_test extends phpbb_database_test_case  {  	public function getDataSet() @@ -161,7 +159,10 @@ class phpbb_log_function_add_log_test extends phpbb_database_test_case  		$db = $this->new_dbal();  		$cache = new phpbb_mock_cache;  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$auth = $this->getMock('\phpbb\auth\auth');  		$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); diff --git a/tests/log/function_view_log_test.php b/tests/log/function_view_log_test.php index 02e0b3912f..ee9c3e5893 100644 --- a/tests/log/function_view_log_test.php +++ b/tests/log/function_view_log_test.php @@ -11,10 +11,7 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  require_once dirname(__FILE__) . '/../mock/user.php';  require_once dirname(__FILE__) . '/../mock/cache.php'; @@ -46,6 +43,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 0,  				'topic_id'			=> 0, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> 'LOG_INSTALL_INSTALLED 3.1.0-dev', @@ -65,6 +63,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 0,  				'topic_id'			=> 0, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> '{LOG KEY NOT EXISTS}<br />additional_data', @@ -84,6 +83,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 0,  				'topic_id'			=> 0, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> '{LOG CRITICAL}<br />critical data', @@ -103,10 +103,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 12,  				'topic_id'			=> 34, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> '{LOG MOD}',  				'viewtopic'			=> '', +				'viewpost'			=> '',  				'viewlogs'			=> '',  			),  			5 => array( @@ -124,10 +126,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 12,  				'topic_id'			=> 45, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> '{LOG MOD}',  				'viewtopic'			=> '', +				'viewpost'			=> '',  				'viewlogs'			=> '',  			),  			6 => array( @@ -145,10 +149,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 23,  				'topic_id'			=> 56, +				'post_id'			=> 0,  				'viewforum'			=> append_sid("phpBB/viewforum.$phpEx", 'f=23'),  				'action'			=> '{LOG MOD}',  				'viewtopic'			=> append_sid("phpBB/viewtopic.$phpEx", 'f=23&t=56'), +				'viewpost'			=> '',  				'viewlogs'			=> append_sid("phpBB/mcp.$phpEx", 'i=logs&mode=topic_logs&t=56'),  			),  			7 => array( @@ -166,10 +172,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 12,  				'topic_id'			=> 45, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> 'LOG_MOD2',  				'viewtopic'			=> '', +				'viewpost'			=> '',  				'viewlogs'			=> '',  			),  			8 => array( @@ -187,6 +195,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 0,  				'topic_id'			=> 0, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> 'LOG_USER admin', @@ -206,6 +215,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 0,  				'topic_id'			=> 0, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> 'LOG_USER guest', @@ -225,6 +235,7 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 0,  				'topic_id'			=> 0, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> 'LOG_SINGULAR_PLURAL 2', @@ -244,10 +255,12 @@ class phpbb_log_function_view_log_test extends phpbb_database_test_case  				'time'				=> 1,  				'forum_id'			=> 15,  				'topic_id'			=> 3, +				'post_id'			=> 0,  				'viewforum'			=> '',  				'action'			=> 'LOG_MOD3 guest ',  				'viewtopic'			=> '', +				'viewpost'			=> '',  				'viewlogs'			=> '',  			),  		); diff --git a/tests/migrator/convert_timezones_test.php b/tests/migrator/convert_timezones_test.php index 7501ed2ed0..f8d780da0c 100644 --- a/tests/migrator/convert_timezones_test.php +++ b/tests/migrator/convert_timezones_test.php @@ -18,7 +18,8 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case  	public function getDataSet()  	{  		$this->db = $this->new_dbal(); -		$db_tools = new \phpbb\db\tools($this->db); +		$factory = new \phpbb\db\tools\factory(); +		$db_tools = $factory->get($this->db);  		// user_dst doesn't exist anymore, must re-add it to test this  		$db_tools->sql_column_add('phpbb_users', 'user_dst', array('BOOL', 1)); @@ -55,11 +56,12 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case  		global $phpbb_root_path, $phpEx;  		$this->db = $this->new_dbal(); +		$factory = new \phpbb\db\tools\factory();  		$this->migration = new \phpbb\db\migration\data\v310\timezone(  			new \phpbb\config\config(array()),  			$this->db, -			new \phpbb\db\tools($this->db), +			$factory->get($this->db),  			$phpbb_root_path,  			$phpEx,  			'phpbb_' @@ -90,7 +92,8 @@ class phpbb_migrator_convert_timezones_test extends phpbb_database_test_case  		}  		$this->db->sql_freeresult($result); -		$db_tools = new \phpbb\db\tools($this->db); +		$factory = new \phpbb\db\tools\factory(); +		$db_tools = $factory->get($this->db);  		// Remove the user_dst field again  		$db_tools->sql_column_remove('phpbb_users', 'user_dst'); diff --git a/tests/migrator/schema_generator_test.php b/tests/migrator/schema_generator_test.php index 9adf518a5d..1996d207ea 100644 --- a/tests/migrator/schema_generator_test.php +++ b/tests/migrator/schema_generator_test.php @@ -29,8 +29,9 @@ class schema_generator_test extends phpbb_test_case  		parent::setUp();  		$this->config = new \phpbb\config\config(array()); -		$this->db = new \phpbb\db\driver\sqlite(); -		$this->db_tools = new \phpbb\db\tools($this->db); +		$this->db = new \phpbb\db\driver\sqlite3(); +		$factory = new \phpbb\db\tools\factory(); +		$this->db_tools = $factory->get($this->db);  		$this->table_prefix = 'phpbb_';  	} diff --git a/tests/mock/container_builder.php b/tests/mock/container_builder.php index 297e3a65e6..134589b0b8 100644 --- a/tests/mock/container_builder.php +++ b/tests/mock/container_builder.php @@ -52,7 +52,15 @@ class phpbb_mock_container_builder implements ContainerInterface  	{  		if ($this->has($id))  		{ -			return $this->services[$id]; +			$service = $this->services[$id]; +			if (is_array($service) && is_callable($service[0])) +			{ +				return call_user_func_array($service[0], $service[1]); +			} +			else +			{ +				return $service; +			}  		}  		throw new Exception('Could not find service: ' . $id); @@ -180,4 +188,9 @@ class phpbb_mock_container_builder implements ContainerInterface  	public function isScopeActive($name)  	{  	} + +	public function isFrozen() +	{ +		return false; +	}  } diff --git a/tests/mock/controller_helper.php b/tests/mock/controller_helper.php index ae3e7bf432..0116dced49 100644 --- a/tests/mock/controller_helper.php +++ b/tests/mock/controller_helper.php @@ -13,20 +13,6 @@  class phpbb_mock_controller_helper extends \phpbb\controller\helper  { -	public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\controller\provider $provider, \phpbb\extension\manager $manager, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext, $phpbb_root_path_ext) -	{ -		$this->template = $template; -		$this->user = $user; -		$this->config = $config; -		$this->symfony_request = $symfony_request; -		$this->request = $request; -		$this->filesystem = $filesystem; -		$this->phpbb_root_path = $phpbb_root_path; -		$this->php_ext = $php_ext; -		$provider->find_routing_files($manager->get_finder()); -		$this->route_collection = $provider->find($phpbb_root_path_ext)->get_routes(); -	} -  	public function get_current_url()  	{  		return ''; diff --git a/tests/mock/extension_manager.php b/tests/mock/extension_manager.php index 3b759fbbc2..2ce61c5149 100644 --- a/tests/mock/extension_manager.php +++ b/tests/mock/extension_manager.php @@ -18,7 +18,7 @@ class phpbb_mock_extension_manager extends \phpbb\extension\manager  		$this->phpbb_root_path = $phpbb_root_path;  		$this->php_ext = 'php';  		$this->extensions = $extensions; -		$this->filesystem = new \phpbb\filesystem(); +		$this->filesystem = new \phpbb\filesystem\filesystem();  		$this->container = $container;  	}  } diff --git a/tests/mock/fileupload.php b/tests/mock/fileupload.php index 8cc4d77ea1..5a0afc6cd3 100644 --- a/tests/mock/fileupload.php +++ b/tests/mock/fileupload.php @@ -19,9 +19,10 @@ class phpbb_mock_fileupload  {  	public $max_filesize = 100;  	public $error_prefix = ''; +	public $valid_dimensions = true;  	public function valid_dimensions($filespec)  	{ -		return true; +		return $this->valid_dimensions;  	}  } diff --git a/tests/mock/migrator.php b/tests/mock/migrator.php index 293f115335..4d1aca0a0a 100644 --- a/tests/mock/migrator.php +++ b/tests/mock/migrator.php @@ -21,10 +21,6 @@ class phpbb_mock_migrator extends \phpbb\db\migrator  	{  	} -	public function set_migrations($class_names) -	{ -	} -  	public function update()  	{  	} diff --git a/tests/mock/notification_manager.php b/tests/mock/notification_manager.php index 6a590bc0ca..952c0db489 100644 --- a/tests/mock/notification_manager.php +++ b/tests/mock/notification_manager.php @@ -32,19 +32,18 @@ class phpbb_mock_notification_manager  		);  	} -	public function mark_notifications_read() +	public function mark_notifications()  	{  	} -	public function mark_notifications_read_by_parent() +	public function mark_notifications_by_parent()  	{  	} -	public function mark_notifications_read_by_id() +	public function mark_notifications_by_id()  	{  	} -  	public function add_notifications()  	{  		return array(); diff --git a/tests/mock/notification_type_post.php b/tests/mock/notification_type_post.php index 6d8f6dc504..4116fecf5e 100644 --- a/tests/mock/notification_type_post.php +++ b/tests/mock/notification_type_post.php @@ -21,11 +21,12 @@ if (!defined('IN_PHPBB'))  class phpbb_mock_notification_type_post extends \phpbb\notification\type\post  { -	public function __construct($user_loader, $db, $cache, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) +	public function __construct($user_loader, $db, $cache, $language, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table)  	{  		$this->user_loader = $user_loader;  		$this->db = $db;  		$this->cache = $cache; +		$this->language = $language;  		$this->user = $user;  		$this->auth = $auth;  		$this->config = $config; @@ -34,7 +35,6 @@ class phpbb_mock_notification_type_post extends \phpbb\notification\type\post  		$this->php_ext = $php_ext;  		$this->notification_types_table = $notification_types_table; -		$this->notifications_table = $notifications_table; -		$this->user_notifications_table = $user_notifications_table;	 +		$this->user_notifications_table = $user_notifications_table;  	}  } diff --git a/tests/mock/phpbb_di_container_builder.php b/tests/mock/phpbb_di_container_builder.php index 59cdf0bb2b..23dc3d1e8b 100644 --- a/tests/mock/phpbb_di_container_builder.php +++ b/tests/mock/phpbb_di_container_builder.php @@ -17,4 +17,14 @@ class phpbb_mock_phpbb_di_container_builder extends \phpbb\di\container_builder  	{  		return $this->phpbb_root_path . '../../tmp/container.' . $this->php_ext;  	} + +	/** +	 * Get the filename under which the dumped extensions autoloader will be stored. +	 * +	 * @return string Path for dumped extensions autoloader +	 */ +	protected function get_autoload_filename() +	{ +		return $this->phpbb_root_path . '../../tmp/autoload.' . $this->php_ext; +	}  } diff --git a/tests/mock/router.php b/tests/mock/router.php new file mode 100644 index 0000000000..01faa338c5 --- /dev/null +++ b/tests/mock/router.php @@ -0,0 +1,27 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_mock_router extends \phpbb\routing\router +{ +	public function get_matcher() +	{ +		$this->create_new_url_matcher(); +		return parent::get_matcher(); +	} + +	public function get_generator() +	{ +		$this->create_new_url_generator(); +		return parent::get_generator(); +	} +} diff --git a/tests/mock/session_testable.php b/tests/mock/session_testable.php index 29dd2a5bff..2f24978ba8 100644 --- a/tests/mock/session_testable.php +++ b/tests/mock/session_testable.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  /**  * Extends the session class to overwrite the setting of cookies.  * diff --git a/tests/network/checkdnsrr_test.php b/tests/network/checkdnsrr_test.php index a3852b2656..6503a4c40b 100644 --- a/tests/network/checkdnsrr_test.php +++ b/tests/network/checkdnsrr_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  /**  * @group slow  */ diff --git a/tests/network/ftp_fsock_pasv_epsv_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php index 6ed9d61dc0..4ec21b6f75 100644 --- a/tests/network/ftp_fsock_pasv_epsv_test.php +++ b/tests/network/ftp_fsock_pasv_epsv_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php';  /** diff --git a/tests/network/inet_ntop_pton_test.php b/tests/network/inet_ntop_pton_test.php index fae40ad74e..dbd58ce783 100644 --- a/tests/network/inet_ntop_pton_test.php +++ b/tests/network/inet_ntop_pton_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_network_inet_ntop_pton_test extends phpbb_test_case  {  	public function data_provider() diff --git a/tests/network/ip_normalise_test.php b/tests/network/ip_normalise_test.php index 1acfd4521d..52e594e115 100644 --- a/tests/network/ip_normalise_test.php +++ b/tests/network/ip_normalise_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_network_ip_normalise_test extends phpbb_test_case  {  	public function data_provider() diff --git a/tests/notification/base.php b/tests/notification/base.php index 162feae557..b64e25cf8c 100644 --- a/tests/notification/base.php +++ b/tests/notification/base.php @@ -11,6 +11,10 @@  *  */ +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +  require_once dirname(__FILE__) . '/manager_helper.php';  abstract class phpbb_tests_notification_base extends phpbb_database_test_case @@ -39,6 +43,13 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case  		);  	} +	protected function get_notification_methods() +	{ +		return array( +			'notification.method.board', +		); +	} +  	protected function setUp()  	{  		parent::setUp(); @@ -55,55 +66,83 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case  			'allow_bookmarks'		=> true,  			'allow_topic_notify'	=> true,  			'allow_forum_notify'	=> true, +			'allow_board_notifications'	=> true,  		)); -		$user = $this->user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$this->user = $user;  		$this->user_loader = new \phpbb\user_loader($this->db, $phpbb_root_path, $phpEx, 'phpbb_users');  		$auth = $this->auth = new phpbb_mock_notifications_auth(); +		$cache_driver = new \phpbb\cache\driver\dummy();  		$cache = $this->cache = new \phpbb\cache\service( -			new \phpbb\cache\driver\null(), +			$cache_driver,  			$this->config,  			$this->db,  			$phpbb_root_path,  			$phpEx  		); -		 +  		$this->phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$phpbb_container = $this->container = new phpbb_mock_container_builder(); +		$phpbb_container = $this->container = new ContainerBuilder(); +		$loader     = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__ . '/fixtures')); +		$loader->load('services_notification.yml'); +		$phpbb_container->set('user_loader', $this->user_loader); +		$phpbb_container->set('user', $user); +		$phpbb_container->set('language', $lang); +		$phpbb_container->set('config', $this->config); +		$phpbb_container->set('dbal.conn', $this->db); +		$phpbb_container->set('auth', $auth); +		$phpbb_container->set('cache.driver', $cache_driver); +		$phpbb_container->set('cache', $cache); +		$phpbb_container->set('text_formatter.utils', new \phpbb\textformatter\s9e\utils()); +		$phpbb_container->set('dispatcher', $this->phpbb_dispatcher); +		$phpbb_container->setParameter('core.root_path', $phpbb_root_path); +		$phpbb_container->setParameter('core.php_ext', $phpEx); +		$phpbb_container->setParameter('tables.notifications', 'phpbb_notifications'); +		$phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); +		$phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types');  		$this->notifications = new phpbb_notification_manager_helper(  			array(),  			array(),  			$this->container,  			$this->user_loader, -			$this->config,  			$this->phpbb_dispatcher,  			$this->db,  			$this->cache, +			$lang,  			$this->user, -			$phpbb_root_path, -			$phpEx,  			'phpbb_notification_types', -			'phpbb_notifications',  			'phpbb_user_notifications'  		);  		$phpbb_container->set('notification_manager', $this->notifications); +		$phpbb_container->compile();  		$this->notifications->setDependencies($this->auth, $this->config);  		$types = array();  		foreach ($this->get_notification_types() as $type)  		{ -			$type_parts = explode('.', $type); -			$class = $this->build_type('phpbb\notification\type\\' . array_pop($type_parts)); +			$class = $this->build_type($type);  			$types[$type] = $class; -			$this->container->set($type, $class);  		}  		$this->notifications->set_var('notification_types', $types); +		$methods = array(); +		foreach ($this->get_notification_methods() as $method) +		{ +			$class = $this->container->get($method); + +			$methods[$method] = $class; +		} + +		$this->notifications->set_var('notification_methods', $methods); +  		$this->db->sql_query('DELETE FROM phpbb_notification_types');  		$this->db->sql_query('DELETE FROM phpbb_notifications');  		$this->db->sql_query('DELETE FROM phpbb_user_notifications'); @@ -111,14 +150,14 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case  	protected function build_type($type)  	{ -		global $phpbb_root_path, $phpEx; +		$instance = $this->container->get($type); -		return new $type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $phpbb_root_path, $phpEx, 'phpbb_notification_types', 'phpbb_notifications', 'phpbb_user_notifications'); +		return $instance;  	}  	protected function assert_notifications($expected, $options = array())  	{ -		$notifications = $this->notifications->load_notifications(array_merge(array( +		$notifications = $this->notifications->load_notifications('notification.method.board', array_merge(array(  			'count_unread'	=> true,  			'order_by'		=> 'notification_time',  			'order_dir'		=> 'ASC', diff --git a/tests/notification/convert_test.php b/tests/notification/convert_test.php index 32ab34c9bc..4a7fd89409 100644 --- a/tests/notification/convert_test.php +++ b/tests/notification/convert_test.php @@ -28,11 +28,12 @@ class phpbb_notification_convert_test extends phpbb_database_test_case  		global $phpbb_root_path, $phpEx;  		$this->db = $this->new_dbal(); +		$factory = new \phpbb\db\tools\factory();  		$this->migration = new \phpbb\db\migration\data\v310\notification_options_reconvert(  			new \phpbb\config\config(array()),  			$this->db, -			new \phpbb\db\tools($this->db), +			$factory->get($this->db),  			$phpbb_root_path,  			$phpEx,  			'phpbb_' diff --git a/tests/notification/ext/test/notification/type/test.php b/tests/notification/ext/test/notification/type/test.php index b02a563f06..7f3b4a4ef1 100644 --- a/tests/notification/ext/test/notification/type/test.php +++ b/tests/notification/ext/test/notification/type/test.php @@ -47,12 +47,13 @@ class test extends \phpbb\notification\type\base  	{  		$this->notification_time = $post['post_time']; -		return parent::create_insert_array($post, $pre_create_data); +		parent::create_insert_array($post, $pre_create_data);  	}  	public function create_update_array($type_data)  	{ -		$data = $this->create_insert_array($type_data); +		$this->create_insert_array($type_data); +		$data = $this->get_insert_array();  		// Unset data unique to each row  		unset( diff --git a/tests/notification/fixtures/services_notification.yml b/tests/notification/fixtures/services_notification.yml new file mode 100644 index 0000000000..6e68cccff6 --- /dev/null +++ b/tests/notification/fixtures/services_notification.yml @@ -0,0 +1,76 @@ +imports: +    - { resource: ../../../phpBB/config/default/container/services_notification.yml } + +services: +    notification_manager: +        synthetic: true + +    user_loader: +        synthetic: true + +    user: +        synthetic: true + +    config: +        synthetic: true + +    dbal.conn: +        synthetic: true + +    language: +        synthetic: true + +    auth: +        synthetic: true + +    cache.driver: +        synthetic: true + +    group_helper: +        synthetic: true + +    path_helper: +        synthetic: true + +    groupposition.legend: +        synthetic: true + +    groupposition.teampage: +        synthetic: true + +    groupposition.teampage: +        synthetic: true + +    text_formatter.s9e.factory: +        synthetic: true + +    text_formatter.s9e.quote_helper: +        synthetic: true + +    text_formatter.parser: +        synthetic: true + +    text_formatter.s9e.parser: +        synthetic: true + +    text_formatter.renderer: +        synthetic: true + +    text_formatter.s9e.renderer: +        synthetic: true + +    text_formatter.utils: +        synthetic: true + +    text_formatter.s9e.utils: +        synthetic: true + +    text_formatter.data_access: +        synthetic: true + +    test: +        class: phpbb\notification\type\test +        scope: prototype +        parent: notification.type.base +        tags: +            - { name: notification.type } diff --git a/tests/notification/fixtures/submit_post_notification.type.bookmark.xml b/tests/notification/fixtures/submit_post_notification.type.bookmark.xml index a1413e2cf8..7f069abc59 100644 --- a/tests/notification/fixtures/submit_post_notification.type.bookmark.xml +++ b/tests/notification/fixtures/submit_post_notification.type.bookmark.xml @@ -126,35 +126,35 @@  			<value>notification.type.bookmark</value>  			<value>0</value>  			<value>2</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.bookmark</value>  			<value>0</value>  			<value>3</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.bookmark</value>  			<value>0</value>  			<value>4</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.bookmark</value>  			<value>0</value>  			<value>5</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.bookmark</value>  			<value>0</value>  			<value>6</value> -			<value></value> +			<value>notification.method.board</value>  			<value>0</value>  		</row>  	</table> diff --git a/tests/notification/fixtures/submit_post_notification.type.post.xml b/tests/notification/fixtures/submit_post_notification.type.post.xml index ed75787c70..a4bf9d3ee4 100644 --- a/tests/notification/fixtures/submit_post_notification.type.post.xml +++ b/tests/notification/fixtures/submit_post_notification.type.post.xml @@ -156,49 +156,49 @@  			<value>notification.type.post</value>  			<value>0</value>  			<value>2</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.post</value>  			<value>0</value>  			<value>3</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.post</value>  			<value>0</value>  			<value>4</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.post</value>  			<value>0</value>  			<value>5</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.post</value>  			<value>0</value>  			<value>6</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.post</value>  			<value>0</value>  			<value>7</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.post</value>  			<value>0</value>  			<value>8</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  	</table> diff --git a/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml b/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml index 2dea8e34dd..0a955c48d2 100644 --- a/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml +++ b/tests/notification/fixtures/submit_post_notification.type.post_in_queue.xml @@ -110,49 +110,49 @@  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>2</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>3</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>4</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>5</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>6</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>7</value> -			<value></value> +			<value>notification.method.board</value>  			<value>0</value>  		</row>  		<row>  			<value>notification.type.needs_approval</value>  			<value>0</value>  			<value>9</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  	</table> diff --git a/tests/notification/fixtures/submit_post_notification.type.quote.xml b/tests/notification/fixtures/submit_post_notification.type.quote.xml index dd5bc620cd..c66830fbf5 100644 --- a/tests/notification/fixtures/submit_post_notification.type.quote.xml +++ b/tests/notification/fixtures/submit_post_notification.type.quote.xml @@ -98,35 +98,35 @@  			<value>notification.type.quote</value>  			<value>0</value>  			<value>2</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.quote</value>  			<value>0</value>  			<value>3</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.quote</value>  			<value>0</value>  			<value>4</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.quote</value>  			<value>0</value>  			<value>5</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.quote</value>  			<value>0</value>  			<value>6</value> -			<value></value> +			<value>notification.method.board</value>  			<value>0</value>  		</row>  	</table> diff --git a/tests/notification/fixtures/submit_post_notification.type.topic.xml b/tests/notification/fixtures/submit_post_notification.type.topic.xml index 1ba8d05699..e0f6583f48 100644 --- a/tests/notification/fixtures/submit_post_notification.type.topic.xml +++ b/tests/notification/fixtures/submit_post_notification.type.topic.xml @@ -106,28 +106,28 @@  			<value>notification.type.topic</value>  			<value>0</value>  			<value>2</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.topic</value>  			<value>0</value>  			<value>6</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.topic</value>  			<value>0</value>  			<value>7</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  		<row>  			<value>notification.type.topic</value>  			<value>0</value>  			<value>8</value> -			<value></value> +			<value>notification.method.board</value>  			<value>1</value>  		</row>  	</table> diff --git a/tests/notification/group_request_test.php b/tests/notification/group_request_test.php index 0d1bda95ce..92e758a336 100644 --- a/tests/notification/group_request_test.php +++ b/tests/notification/group_request_test.php @@ -12,7 +12,6 @@  */  require_once dirname(__FILE__) . '/base.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_notification_group_request_test extends phpbb_tests_notification_base  { @@ -40,8 +39,6 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas  		include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);  		include_once($phpbb_root_path . 'includes/functions_content.' . $phpEx); -		set_config(false, false, false, $this->config); -  		$this->container->set('groupposition.legend', new \phpbb\groupposition\legend(  			$this->db,  			$this->user @@ -51,8 +48,14 @@ class phpbb_notification_group_request_test extends phpbb_tests_notification_bas  			$this->user,  			$this->cache->get_driver()  		)); +		$this->container->set('group_helper', new \phpbb\group\helper( +			new \phpbb\language\language( +				new phpbb\language\language_file_loader($phpbb_root_path, $phpEx) +			) +		));  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher; -		$phpbb_log = new \phpbb\log\null(); +		$phpbb_log = new \phpbb\log\dummy(); +		$this->get_test_case_helpers()->set_s9e_services();  		// Now on to the actual test diff --git a/tests/notification/manager_helper.php b/tests/notification/manager_helper.php index 75b7275d3a..2e8699e1e0 100644 --- a/tests/notification/manager_helper.php +++ b/tests/notification/manager_helper.php @@ -37,35 +37,4 @@ class phpbb_notification_manager_helper extends \phpbb\notification\manager  		$this->auth = $auth;  		$this->config = $config;  	} - -	/** -	* Helper to get the notifications item type class and set it up -	*/ -	public function get_item_type_class($item_type, $data = array()) -	{ -		$item_parts = explode('.', $item_type); -		$item_type = 'phpbb\notification\type\\' . array_pop($item_parts); - -		$item = new $item_type($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table); - -		$item->set_notification_manager($this); - -		$item->set_initial_data($data); - -		return $item; -	} - -	/** -	* Helper to get the notifications method class and set it up -	*/ -	public function get_method_class($method_name) -	{ -		$method_name = 'phpbb\notification\method\\' . $method_name; - -		$method = new $method_name($this->user_loader, $this->db, $this->cache->get_driver(), $this->user, $this->auth, $this->config, $this->phpbb_root_path, $this->php_ext, $this->notification_types_table, $this->notifications_table, $this->user_notifications_table); - -		$method->set_notification_manager($this); - -		return $method; -	}  } diff --git a/tests/notification/notification_test.php b/tests/notification/notification_test.php index 79fa5338c4..ec42aa193c 100644 --- a/tests/notification/notification_test.php +++ b/tests/notification/notification_test.php @@ -29,7 +29,7 @@ class phpbb_notification_test extends phpbb_tests_notification_base  		$quote_type_id = $this->notifications->get_notification_type_id('notification.type.quote');  		$test_type_id = $this->notifications->get_notification_type_id('test'); -		$this->assertEquals(array( +		self::assertEquals(array(  				'test'	=> $test_type_id,  				'notification.type.quote'	=> $quote_type_id,  				'notification.type.post'	=> $post_type_id, @@ -40,13 +40,13 @@ class phpbb_notification_test extends phpbb_tests_notification_base  				'notification.type.post',  			)  		)); -		$this->assertEquals($quote_type_id, $this->notifications->get_notification_type_id('notification.type.quote')); +		self::assertEquals($quote_type_id, $this->notifications->get_notification_type_id('notification.type.quote'));  		try  		{ -			$this->assertEquals(false, $this->notifications->get_notification_type_id('fail')); +			self::assertEquals(false, $this->notifications->get_notification_type_id('fail')); -			$this->fail('Non-existent type should throw an exception'); +			self::fail('Non-existent type should throw an exception');  		}  		catch (Exception $e) {}  	} @@ -55,15 +55,15 @@ class phpbb_notification_test extends phpbb_tests_notification_base  	{  		$subscription_types = $this->notifications->get_subscription_types(); -		$this->assertArrayHasKey('NOTIFICATION_GROUP_MISCELLANEOUS', $subscription_types); -		$this->assertArrayHasKey('NOTIFICATION_GROUP_POSTING', $subscription_types); +		self::assertArrayHasKey('NOTIFICATION_GROUP_MISCELLANEOUS', $subscription_types); +		self::assertArrayHasKey('NOTIFICATION_GROUP_POSTING', $subscription_types); -		$this->assertArrayHasKey('notification.type.bookmark', $subscription_types['NOTIFICATION_GROUP_POSTING']); -		$this->assertArrayHasKey('notification.type.post', $subscription_types['NOTIFICATION_GROUP_POSTING']); -		$this->assertArrayHasKey('notification.type.quote', $subscription_types['NOTIFICATION_GROUP_POSTING']); -		$this->assertArrayHasKey('notification.type.topic', $subscription_types['NOTIFICATION_GROUP_POSTING']); +		self::assertArrayHasKey('notification.type.bookmark', $subscription_types['NOTIFICATION_GROUP_POSTING']); +		self::assertArrayHasKey('notification.type.post', $subscription_types['NOTIFICATION_GROUP_POSTING']); +		self::assertArrayHasKey('notification.type.quote', $subscription_types['NOTIFICATION_GROUP_POSTING']); +		self::assertArrayHasKey('notification.type.topic', $subscription_types['NOTIFICATION_GROUP_POSTING']); -		$this->assertArrayHasKey('notification.type.pm', $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']); +		self::assertArrayHasKey('notification.type.pm', $subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']);  		//get_subscription_types  		//get_subscription_methods @@ -72,33 +72,33 @@ class phpbb_notification_test extends phpbb_tests_notification_base  	public function test_subscriptions()  	{  		$expected_subscriptions = array( -			'notification.type.post'		=> array(''), -			'notification.type.topic'		=> array(''), -			'notification.type.quote'		=> array(''), -			'notification.type.bookmark'	=> array(''), -			'test'		=> array(''), -			'notification.type.pm'		=> array(''), +			'notification.type.post'		=> array('notification.method.board'), +			'notification.type.topic'		=> array('notification.method.board'), +			'notification.type.quote'		=> array('notification.method.board'), +			'notification.type.bookmark'	=> array('notification.method.board'), +			'test'		=> array('notification.method.board'), +			'notification.type.pm'		=> array('notification.method.board'),  		);  		$subscriptions = $this->notifications->get_global_subscriptions(2); -  		foreach ($expected_subscriptions as $item_type => $methods)  		{ +			self::assertArrayHasKey($item_type, $subscriptions);  			$this->assert_array_content_equals($methods, $subscriptions[$item_type]);  		}  		foreach ($subscriptions as $item_type => $methods)  		{ -			$this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]);	 +			$this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]);  		} -		$this->notifications->delete_subscription('notification.type.post', 0, '', 2); +		$this->notifications->delete_subscription('notification.type.post', 0, 'notification.method.board', 2); -		$this->assertArrayNotHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); +		self::assertArrayNotHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); -		$this->notifications->add_subscription('notification.type.post', 0, '', 2); +		$this->notifications->add_subscription('notification.type.post', 0, 'notification.method.board', 2); -		$this->assertArrayHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2)); +		self::assertArrayHasKey('notification.type.post', $this->notifications->get_global_subscriptions(2));  	}  	public function test_notifications() @@ -124,11 +124,11 @@ class phpbb_notification_test extends phpbb_tests_notification_base  			'user_id'			=> 0,  		))); -		$this->assertEquals(array( +		self::assertEquals(array(  				'notifications'		=> array(),  				'unread_count'		=> 0,  				'total_count'		=> 0, -		), $this->notifications->load_notifications(array( +		), $this->notifications->load_notifications('notification.method.board', array(  			'count_unread'	=> true,  		))); diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php index 5e770f71c9..21559c42a5 100644 --- a/tests/notification/submit_post_base.php +++ b/tests/notification/submit_post_base.php @@ -11,10 +11,11 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_posting.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';  abstract class phpbb_notification_submit_post_base extends phpbb_database_test_case  { @@ -50,7 +51,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c  	{  		parent::setUp(); -		global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path; +		global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $lang, $user, $request, $phpEx, $phpbb_root_path, $user_loader;  		// Database  		$this->db = $this->new_dbal(); @@ -69,12 +70,15 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c  			)));  		// Config -		$config = new \phpbb\config\config(array('num_topics' => 1,'num_posts' => 1,)); -		set_config(null, null, null, $config); -		set_config_count(null, null, null, $config); +		$config = new \phpbb\config\config(array( +			'num_topics' => 1, +			'num_posts' => 1, +			'allow_board_notifications'	=> true, +		)); +		$cache_driver = new \phpbb\cache\driver\dummy();  		$cache = new \phpbb\cache\service( -			new \phpbb\cache\driver\null(), +			$cache_driver,  			$config,  			$db,  			$phpbb_root_path, @@ -84,8 +88,14 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c  		// Event dispatcher  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		// Language +		$lang = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +  		// User -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$user = $this->getMock('\phpbb\user', array(), array( +			$lang, +			'\phpbb\datetime' +		));  		$user->ip = '';  		$user->data = array(  			'user_id'		=> 2, @@ -98,34 +108,47 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c  		$type_cast_helper = $this->getMock('\phpbb\request\type_cast_helper_interface');  		$request = $this->getMock('\phpbb\request\request'); -		// Container -		$phpbb_container = new phpbb_mock_container_builder();  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); -  		$user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE); +		// Container +		$phpbb_container = new ContainerBuilder(); +		$loader     = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__ . '/fixtures')); +		$loader->load('services_notification.yml'); +		$phpbb_container->set('user_loader', $user_loader); +		$phpbb_container->set('user', $user); +		$phpbb_container->set('language', $lang); +		$phpbb_container->set('config', $config); +		$phpbb_container->set('dbal.conn', $db); +		$phpbb_container->set('auth', $auth); +		$phpbb_container->set('cache.driver', $cache_driver); +		$phpbb_container->set('cache', $cache); +		$phpbb_container->set('text_formatter.utils', new \phpbb\textformatter\s9e\utils()); +		$phpbb_container->set('dispatcher', $phpbb_dispatcher); +		$phpbb_container->setParameter('core.root_path', $phpbb_root_path); +		$phpbb_container->setParameter('core.php_ext', $phpEx); +		$phpbb_container->setParameter('tables.notifications', 'phpbb_notifications'); +		$phpbb_container->setParameter('tables.user_notifications', 'phpbb_user_notifications'); +		$phpbb_container->setParameter('tables.notification_types', 'phpbb_notification_types'); +		$phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE)); +		$phpbb_container->compile(); +  		// Notification Types  		$notification_types = array('quote', 'bookmark', 'post', 'post_in_queue', 'topic', 'topic_in_queue', 'approve_topic', 'approve_post');  		$notification_types_array = array();  		foreach ($notification_types as $type)  		{ -			$class_name = '\phpbb\notification\type\\' . $type; -			$class = new $class_name( -				$user_loader, $db, $cache->get_driver(), $user, $auth, $config, -				$phpbb_root_path, $phpEx, -				NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE); - -			$phpbb_container->set('notification.type.' . $type, $class); - +			$class = $phpbb_container->get('notification.type.' . $type);  			$notification_types_array['notification.type.' . $type] = $class;  		} +		// Methods Types +		$notification_methods_array = array('notification.method.board' => $phpbb_container->get('notification.method.board')); +  		// Notification Manager -		$phpbb_notifications = new \phpbb\notification\manager($notification_types_array, array(), -			$phpbb_container, $user_loader, $config, $phpbb_dispatcher, $db, $cache, $user, -			$phpbb_root_path, $phpEx, -			NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE); +		$phpbb_notifications = new \phpbb\notification\manager($notification_types_array, $notification_methods_array, +			$phpbb_container, $user_loader, $phpbb_dispatcher, $db, $cache, $lang, $user, +			NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE);  		$phpbb_container->set('notification_manager', $phpbb_notifications);  	} diff --git a/tests/notification/submit_post_type_quote_test.php b/tests/notification/submit_post_type_quote_test.php index 61e3840773..3fab8c05ba 100644 --- a/tests/notification/submit_post_type_quote_test.php +++ b/tests/notification/submit_post_type_quote_test.php @@ -51,6 +51,9 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_  	*/  	public function submit_post_data()  	{ +		// The new mock container is needed because the data providers may be executed before phpunit call setUp() +		$parser = $this->get_test_case_helpers()->set_s9e_services(new phpbb_mock_container_builder())->get('text_formatter.parser'); +  		return array(  			/**  			* Normal post @@ -65,15 +68,15 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_  			*/  			array(  				array( -					'message'			=> implode(' ', array( -						'[quote="poster":uid]poster should not be notified[/quote:uid]', -						'[quote="test":uid]test should be notified[/quote:uid]', -						'[quote="unauthorized":uid]unauthorized to read, should not receive a notification[/quote:uid]', -						'[quote="notified":uid]already notified, should not receive a new notification[/quote:uid]', -						'[quote="disabled":uid]option disabled, should not receive a notification[/quote:uid]', -						'[quote="default":uid]option set to default, should receive a notification[/quote:uid]', -						'[quote="doesn\'t exist":uid]user does not exist, should not receive a notification[/quote:uid]', -					)), +					'message'			=> $parser->parse(implode(' ', array( +						'[quote="poster"]poster should not be notified[/quote]', +						'[quote="test"]test should be notified[/quote]', +						'[quote="unauthorized"]unauthorized to read, should not receive a notification[/quote]', +						'[quote="notified"]already notified, should not receive a new notification[/quote]', +						'[quote="disabled"]option disabled, should not receive a notification[/quote]', +						'[quote="default"]option set to default, should receive a notification[/quote]', +						'[quote="doesn\'t exist"]user does not exist, should not receive a notification[/quote]', +					))),  					'bbcode_uid'		=> 'uid',  				),  				array( @@ -94,15 +97,15 @@ class phpbb_notification_submit_post_type_quote_test extends phpbb_notification_  			*/  			array(  				array( -					'message'			=> implode(' ', array( -						'[quote="poster":uid]poster should not be notified[/quote:uid]', -						'[quote="test":uid]test should be notified[/quote:uid]', -						'[quote="unauthorized":uid]unauthorized to read, should not receive a notification[/quote:uid]', -						'[quote="notified":uid]already notified, should not receive a new notification[/quote:uid]', -						'[quote="disabled":uid]option disabled, should not receive a notification[/quote:uid]', -						'[quote="default":uid]option set to default, should receive a notification[/quote:uid]', -						'[quote="doesn\'t exist":uid]user does not exist, should not receive a notification[/quote:uid]', -					)), +					'message'			=> $parser->parse(implode(' ', array( +						'[quote="poster"]poster should not be notified[/quote]', +						'[quote="test"]test should be notified[/quote]', +						'[quote="unauthorized"]unauthorized to read, should not receive a notification[/quote]', +						'[quote="notified"]already notified, should not receive a new notification[/quote]', +						'[quote="disabled"]option disabled, should not receive a notification[/quote]', +						'[quote="default"]option set to default, should receive a notification[/quote]', +						'[quote="doesn\'t exist"]user does not exist, should not receive a notification[/quote]', +					))),  					'bbcode_uid'		=> 'uid',  					'force_approved_state' => false,  				), diff --git a/tests/notification/submit_post_type_topic_test.php b/tests/notification/submit_post_type_topic_test.php index c095fbc4ba..f14f305517 100644 --- a/tests/notification/submit_post_type_topic_test.php +++ b/tests/notification/submit_post_type_topic_test.php @@ -42,7 +42,7 @@ class phpbb_notification_submit_post_type_topic_test extends phpbb_notification_  				),  			))); -		$phpbb_log = $this->getMock('\phpbb\log\null'); +		$phpbb_log = $this->getMock('\phpbb\log\dummy');  	}  	/** diff --git a/tests/notification/user_list_trim_test.php b/tests/notification/user_list_trim_test.php index c43eff729c..7d4dff6024 100644 --- a/tests/notification/user_list_trim_test.php +++ b/tests/notification/user_list_trim_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  {  	protected $notification; @@ -33,11 +30,9 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  		$db = $this->new_dbal();  		$config = new \phpbb\config\config(array()); -		set_config(null, null, null, $config); -		set_config_count(null, null, null, $config);  		$cache = new \phpbb\cache\service( -			new \phpbb\cache\driver\null(), +			new \phpbb\cache\driver\dummy(),  			$config,  			$db,  			$phpbb_root_path, @@ -53,15 +48,17 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  				array('u_viewprofile', 1, false),  			))); -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->data = array('user_lang' => 'en'); -		$user->add_lang('common'); +		$lang->add_lang('common');  		$user_loader = new phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);  		$user_loader->load_users(array(2, 3, 4, 5, 6));  		$this->notification = new phpbb_mock_notification_type_post( -			$user_loader, null, null, $user, null, null, $phpbb_root_path, $phpEx, null, null, null +			$user_loader, null, null, $lang, $user, null, null, $phpbb_root_path, $phpEx, null, null  		);  	} @@ -73,7 +70,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  					'topic_title'	=> 'Test',  					'poster_id'		=> 2,  					'post_username'	=> 'A', -					'responders'	=> null,			 +					'responders'	=> null,  				),  				'<strong>Reply</strong> from A in topic:',  			), @@ -84,7 +81,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  					'post_username'	=> 'A',  					'responders'	=> array(  						array('username' => '', 'poster_id' => 3), -					),			 +					),  				),  				'<strong>Reply</strong> from A and <span class="username">B</span> in topic:',  			), @@ -96,7 +93,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  					'responders'	=> array(  						array('username' => '', 'poster_id' => 3),  						array('username' => '', 'poster_id' => 4), -					),			 +					),  				),  				'<strong>Reply</strong> from A, <span class="username">B</span>, and <span class="username">C</span> in topic:',  			), @@ -109,7 +106,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  						array('username' => '', 'poster_id' => 3),  						array('username' => '', 'poster_id' => 4),  						array('username' => '', 'poster_id' => 5), -					),			 +					),  				),  				'<strong>Reply</strong> from A, <span class="username">B</span>, <span class="username">C</span>, and <span class="username">D</span> in topic:',  			), @@ -123,7 +120,7 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case  						array('username' => '', 'poster_id' => 4),  						array('username' => '', 'poster_id' => 5),  						array('username' => '', 'poster_id' => 6), -					),			 +					),  				),  				'<strong>Reply</strong> from A, <span class="username">B</span>, <span class="username">C</span>, and 2 others in topic:',  			), diff --git a/tests/pagination/config/routing.yml b/tests/pagination/config/test/routing/environment.yml index 2ce082c9d1..2ce082c9d1 100644 --- a/tests/pagination/config/routing.yml +++ b/tests/pagination/config/test/routing/environment.yml diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php index ea6dd999c3..024b6fc02d 100644 --- a/tests/pagination/pagination_test.php +++ b/tests/pagination/pagination_test.php @@ -26,27 +26,27 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case  	{  		parent::setUp(); -		global $phpbb_dispatcher; +		global $phpbb_dispatcher, $phpbb_root_path, $phpEx;  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$this->user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$this->user->expects($this->any())  			->method('lang')  			->will($this->returnCallback(array($this, 'return_callback_implode'))); -		$filesystem = new \phpbb\filesystem(); +		$filesystem = new \phpbb\filesystem\filesystem();  		$manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array()); -		$finder = new \phpbb\finder( -			$filesystem, -			dirname(__FILE__) . '/', -			new phpbb_mock_cache() -		); -		$finder->set_extensions(array_keys($manager->all_enabled()));  		$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1')); -		$provider = new \phpbb\controller\provider(); -		$provider->find_routing_files($finder); -		$provider->find(dirname(__FILE__) . '/'); + +		$loader = new \Symfony\Component\Routing\Loader\YamlFileLoader( +			new \phpbb\routing\file_locator($filesystem, dirname(__FILE__) . '/') +		); +		$resources_locator = new \phpbb\routing\resources_locator\default_resources_locator(dirname(__FILE__) . '/', PHPBB_ENVIRONMENT, $manager); +		$router = new phpbb_mock_router(new phpbb_mock_container_builder(), $resources_locator, $loader, dirname(__FILE__) . '/', 'php');  		$request = new phpbb_mock_request();  		$request->overwrite('SCRIPT_NAME', '/app.php', \phpbb\request\request_interface::SERVER); @@ -57,7 +57,8 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case  			$request  		); -		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $provider, $manager, $symfony_request, $request, $filesystem, '', 'php', dirname(__FILE__) . '/'); +		$this->routing_helper = new \phpbb\routing\helper($this->config, $router, $symfony_request, $request, $filesystem, '', 'php'); +		$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $symfony_request, $request, $this->routing_helper);  		$this->pagination = new \phpbb\pagination($this->template, $this->user, $this->helper, $phpbb_dispatcher);  	} diff --git a/tests/path_helper/path_helper_test.php b/tests/path_helper/path_helper_test.php index 73f0e6bafc..49dd40fbec 100644 --- a/tests/path_helper/path_helper_test.php +++ b/tests/path_helper/path_helper_test.php @@ -21,14 +21,14 @@ class phpbb_path_helper_test extends phpbb_test_case  	{  		parent::setUp(); -		$filesystem = new \phpbb\filesystem(); +		$filesystem = new \phpbb\filesystem\filesystem();  		$this->set_phpbb_root_path($filesystem);  		$this->path_helper = new \phpbb\path_helper(  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			new \phpbb\filesystem\filesystem(),  			$this->getMock('\phpbb\request\request'),  			$this->phpbb_root_path,  			'php' @@ -56,7 +56,7 @@ class phpbb_path_helper_test extends phpbb_test_case  	public function basic_update_web_root_path_data()  	{ -		$filesystem = new \phpbb\filesystem(); +		$filesystem = new \phpbb\filesystem\filesystem();  		$this->set_phpbb_root_path($filesystem);  		return array( @@ -90,7 +90,7 @@ class phpbb_path_helper_test extends phpbb_test_case  	public function update_web_root_path_data()  	{ -		$this->set_phpbb_root_path(new \phpbb\filesystem()); +		$this->set_phpbb_root_path(new \phpbb\filesystem\filesystem());  		return array(  			array( @@ -135,6 +135,43 @@ class phpbb_path_helper_test extends phpbb_test_case  				'/phpbb3-fork/phpBB/app.php',  				'./../',  			), + +			// No correction if the path is already prepend by the web root path +			array( +				'./../' . $this->phpbb_root_path . 'test.php', +				'//', +				null, +				null, +				'', +			), +			array( +				'./../' . $this->phpbb_root_path . 'test.php', +				'//', +				'foo/bar.php', +				'bar.php', +				'', +			), +			array( +				'./../../' . $this->phpbb_root_path . 'test.php', +				'/foo/template', +				'/phpbb3-fork/phpBB/app.php/foo/template', +				'/phpbb3-fork/phpBB/app.php', +				'', +			), +			array( +				'./../' . $this->phpbb_root_path . 'test.php', +				'/foo/template', +				'/phpbb3-fork/phpBB/foo/template', +				'/phpbb3-fork/phpBB/app.php', +				'', +			), +			array( +				'./../'.$this->phpbb_root_path . 'test.php', +				'/', +				'/phpbb3-fork/phpBB/app.php/', +				'/phpbb3-fork/phpBB/app.php', +				'', +			),  		);  	} @@ -158,7 +195,7 @@ class phpbb_path_helper_test extends phpbb_test_case  		$path_helper = new \phpbb\path_helper(  			$symfony_request, -			new \phpbb\filesystem(), +			new \phpbb\filesystem\filesystem(),  			$this->getMock('\phpbb\request\request'),  			$this->phpbb_root_path,  			'php' diff --git a/tests/plupload/plupload_test.php b/tests/plupload/plupload_test.php index 2f47bf2b39..3312f4d0a0 100644 --- a/tests/plupload/plupload_test.php +++ b/tests/plupload/plupload_test.php @@ -34,6 +34,10 @@ class phpbb_plupload_test extends phpbb_test_case  	*/  	public function test_generate_resize_string($config_width, $config_height, $expected)  	{ +		global $phpbb_root_path, $phpEx; + +		$lang = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +  		$config = new \phpbb\config\config(array(  			'img_max_width'		=> $config_width,  			'img_max_height'	=> $config_height, @@ -43,8 +47,8 @@ class phpbb_plupload_test extends phpbb_test_case  			'',  			$config,  			new phpbb_mock_request, -			new \phpbb\user('\phpbb\datetime'), -			new \phpbb\php\ini, +			new \phpbb\user($lang, '\phpbb\datetime'), +			new \bantu\IniGetWrapper\IniGetWrapper,  			new \phpbb\mimetype\guesser(array(new \phpbb\mimetype\extension_guesser))  		); diff --git a/tests/privmsgs/delete_user_pms_test.php b/tests/privmsgs/delete_user_pms_test.php index 0f061e9784..9d6ba7a917 100644 --- a/tests/privmsgs/delete_user_pms_test.php +++ b/tests/privmsgs/delete_user_pms_test.php @@ -85,12 +85,14 @@ class phpbb_privmsgs_delete_user_pms_test extends phpbb_database_test_case  	*/  	public function test_delete_user_pms($delete_user, $remaining_privmsgs, $remaining_privmsgs_to)  	{ -		global $db, $phpbb_container; +		global $db, $phpbb_container, $phpbb_root_path;  		$db = $this->new_dbal();  		$phpbb_container = new phpbb_mock_container_builder();  		$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); +		// Works as a workaround for tests +		$phpbb_container->set('attachment.manager', new \phpbb\attachment\delete(new \phpbb\config\config(array()), $db, new \phpbb_mock_event_dispatcher(), new \phpbb\filesystem\filesystem(), new \phpbb\attachment\resync($db), $phpbb_root_path));  		phpbb_delete_user_pms($delete_user); diff --git a/tests/profilefields/type_bool_test.php b/tests/profilefields/type_bool_test.php index 41c40ddb4b..10239172c3 100644 --- a/tests/profilefields/type_bool_test.php +++ b/tests/profilefields/type_bool_test.php @@ -25,7 +25,12 @@ class phpbb_profilefield_type_bool_test extends phpbb_test_case  	*/  	public function setUp()  	{ -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$user->expects($this->any())  			->method('lang')  			->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_date_test.php b/tests/profilefields/type_date_test.php index 123955198e..e0807b2f9b 100644 --- a/tests/profilefields/type_date_test.php +++ b/tests/profilefields/type_date_test.php @@ -25,7 +25,12 @@ class phpbb_profilefield_type_date_test extends phpbb_test_case  	*/  	public function setUp()  	{ -		$this->user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$this->user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$this->user->expects($this->any())  			->method('lang')  			->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_dropdown_test.php b/tests/profilefields/type_dropdown_test.php index 3845a8e96b..ab02353fb9 100644 --- a/tests/profilefields/type_dropdown_test.php +++ b/tests/profilefields/type_dropdown_test.php @@ -25,7 +25,12 @@ class phpbb_profilefield_type_dropdown_test extends phpbb_test_case  	*/  	public function setUp()  	{ -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$user->expects($this->any())  			->method('lang')  			->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_googleplus_test.php b/tests/profilefields/type_googleplus_test.php index f3db6ef01f..9222362214 100644 --- a/tests/profilefields/type_googleplus_test.php +++ b/tests/profilefields/type_googleplus_test.php @@ -11,8 +11,6 @@  *  */ -require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_profilefield_type_googleplus_test extends phpbb_test_case  {  	protected  $field; @@ -21,7 +19,11 @@ class phpbb_profilefield_type_googleplus_test extends phpbb_test_case  	{  		parent::setUp(); -		$user = new \phpbb\user('\phpbb\datetime'); +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->add_lang('ucp');  		$request = $this->getMock('\phpbb\request\request');  		$template = $this->getMock('\phpbb\template\template'); diff --git a/tests/profilefields/type_int_test.php b/tests/profilefields/type_int_test.php index 07b22525e2..33f3f575c8 100644 --- a/tests/profilefields/type_int_test.php +++ b/tests/profilefields/type_int_test.php @@ -24,7 +24,12 @@ class phpbb_profilefield_type_int_test extends phpbb_test_case  	*/  	public function setUp()  	{ -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$user->expects($this->any())  			->method('lang')  			->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/profilefields/type_string_test.php b/tests/profilefields/type_string_test.php index 0417afbfab..7c7fa3f3e6 100644 --- a/tests/profilefields/type_string_test.php +++ b/tests/profilefields/type_string_test.php @@ -11,10 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_profilefield_type_string_test extends phpbb_test_case  {  	protected $cp; @@ -28,9 +24,12 @@ class phpbb_profilefield_type_string_test extends phpbb_test_case  	*/  	public function setUp()  	{ -		global $request, $user, $cache; +		global $request, $user, $cache, $phpbb_root_path, $phpEx; -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$cache = new phpbb_mock_cache;  		$user->expects($this->any())  			->method('lang') diff --git a/tests/profilefields/type_url_test.php b/tests/profilefields/type_url_test.php index cc37f04f30..1d90e2c34c 100644 --- a/tests/profilefields/type_url_test.php +++ b/tests/profilefields/type_url_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_profilefield_type_url_test extends phpbb_test_case  {  	protected $cp; @@ -26,7 +24,12 @@ class phpbb_profilefield_type_url_test extends phpbb_test_case  	*/  	public function setUp()  	{ -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		global $phpbb_root_path, $phpEx; + +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$user->expects($this->any())  			->method('lang')  			->will($this->returnCallback(array($this, 'return_callback_implode'))); diff --git a/tests/random/gen_rand_string_test.php b/tests/random/gen_rand_string_test.php index 1d12d0622c..a9d1ea20de 100644 --- a/tests/random/gen_rand_string_test.php +++ b/tests/random/gen_rand_string_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_random_gen_rand_string_test extends phpbb_test_case  {  	const TEST_COUNT = 100; diff --git a/tests/regex/censor_test.php b/tests/regex/censor_test.php index 50c6778c8c..5a516b71de 100644 --- a/tests/regex/censor_test.php +++ b/tests/regex/censor_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_regex_censor_test extends phpbb_test_case  {  	public function censor_test_data() @@ -37,18 +35,8 @@ class phpbb_regex_censor_test extends phpbb_test_case  	*/  	public function test_censor_unicode($pattern, $subject)  	{ -		$regex = get_censor_preg_expression($pattern, true); - -		$this->assertRegExp($regex, $subject); -	} - -	/** -	* @dataProvider censor_test_data -	*/ -	public function test_censor_no_unicode($pattern, $subject) -	{ -		$regex = get_censor_preg_expression($pattern, false); +		$regex = get_censor_preg_expression($pattern);  		$this->assertRegExp($regex, $subject);  	} -}
\ No newline at end of file +} diff --git a/tests/regex/email_test.php b/tests/regex/email_test.php index ede35c49bc..5187b8bda6 100644 --- a/tests/regex/email_test.php +++ b/tests/regex/email_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_regex_email_test extends phpbb_test_case  {  	protected $regex; diff --git a/tests/regex/ipv4_test.php b/tests/regex/ipv4_test.php index 62c2567517..e21a2d77fa 100644 --- a/tests/regex/ipv4_test.php +++ b/tests/regex/ipv4_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_regex_ipv4_test extends phpbb_test_case  {  	protected $regex; diff --git a/tests/regex/ipv6_test.php b/tests/regex/ipv6_test.php index 41039c819d..223161df7f 100644 --- a/tests/regex/ipv6_test.php +++ b/tests/regex/ipv6_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_regex_ipv6_test extends phpbb_test_case  {  	protected $regex; diff --git a/tests/regex/password_complexity_test.php b/tests/regex/password_complexity_test.php index 8a1a9edd41..933dc1ac91 100644 --- a/tests/regex/password_complexity_test.php +++ b/tests/regex/password_complexity_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';  class phpbb_password_complexity_test extends phpbb_test_case diff --git a/tests/regex/table_prefix_test.php b/tests/regex/table_prefix_test.php index c593085b25..bf7b59ccc6 100644 --- a/tests/regex/table_prefix_test.php +++ b/tests/regex/table_prefix_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_regex_table_prefix_test extends phpbb_test_case  {  	public function table_prefix_test_data() diff --git a/tests/regex/url_test.php b/tests/regex/url_test.php index e5d7c3256a..5e2a22bf73 100644 --- a/tests/regex/url_test.php +++ b/tests/regex/url_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_regex_url_test extends phpbb_test_case  {  	public function url_test_data() diff --git a/tests/request/request_var_test.php b/tests/request/request_var_test.php index 67712eb6c8..84c81c4e84 100644 --- a/tests/request/request_var_test.php +++ b/tests/request/request_var_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_request_var_test extends phpbb_test_case  {  	/** diff --git a/tests/request/type_cast_helper_test.php b/tests/request/type_cast_helper_test.php index d6ee1dc728..143c05aa9c 100644 --- a/tests/request/type_cast_helper_test.php +++ b/tests/request/type_cast_helper_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_type_cast_helper_test extends phpbb_test_case  {  	private $type_cast_helper; diff --git a/tests/security/base.php b/tests/security/base.php index 330408b448..d2abdbc362 100644 --- a/tests/security/base.php +++ b/tests/security/base.php @@ -46,10 +46,12 @@ abstract class phpbb_security_test_base extends phpbb_test_case  		$request = new phpbb_mock_request(array(), array(), array(), $this->server);  		$symfony_request = new \phpbb\symfony_request($request); -		$phpbb_filesystem = new \phpbb\filesystem(); +		$phpbb_filesystem = new \phpbb\filesystem\filesystem();  		// Set no user and trick a bit to circumvent errors -		$user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->lang = true;  		$user->browser				= $this->server['HTTP_USER_AGENT'];  		$user->referer				= ''; diff --git a/tests/security/extract_current_page_test.php b/tests/security/extract_current_page_test.php index 767b901a43..f764449eca 100644 --- a/tests/security/extract_current_page_test.php +++ b/tests/security/extract_current_page_test.php @@ -13,7 +13,6 @@  require_once dirname(__FILE__) . '/base.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_security_extract_current_page_test extends phpbb_security_test_base  { diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index 0494c55c6d..84d4fcf479 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_compatibility.php'; -  class phpbb_security_hash_test extends phpbb_test_case  {  	public function setUp() diff --git a/tests/security/redirect_test.php b/tests/security/redirect_test.php index a88fc63858..40cb7d2f04 100644 --- a/tests/security/redirect_test.php +++ b/tests/security/redirect_test.php @@ -13,7 +13,6 @@  require_once dirname(__FILE__) . '/base.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_security_redirect_test extends phpbb_security_test_base  { @@ -67,7 +66,7 @@ class phpbb_security_redirect_test extends phpbb_security_test_base  				new \phpbb\symfony_request(  					new phpbb_mock_request()  				), -				new \phpbb\filesystem(), +				new \phpbb\filesystem\filesystem(),  				$this->getMock('\phpbb\request\request'),  				$this->phpbb_root_path,  				'php' diff --git a/tests/session/append_sid_test.php b/tests/session/append_sid_test.php index 2a1d94514f..4e5a238644 100644 --- a/tests/session/append_sid_test.php +++ b/tests/session/append_sid_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_session_append_sid_test extends phpbb_test_case  { diff --git a/tests/session/check_ban_test.php b/tests/session/check_ban_test.php index 561b7faf49..04da5f08b9 100644 --- a/tests/session/check_ban_test.php +++ b/tests/session/check_ban_test.php @@ -42,7 +42,10 @@ class phpbb_session_check_ban_test extends phpbb_session_test_case  		parent::setUp();  		// Get session here so that config is mocked correctly  		$this->session = $this->session_factory->get_session($this->db); -		global $cache, $config, $phpbb_root_path, $phpEx; +		global $cache, $config, $phpbb_root_path, $phpEx, $phpbb_filesystem; + +		$phpbb_filesystem = new \phpbb\filesystem\filesystem(); +  		$this->backup_cache = $cache;  		// Change the global cache object for this test because  		// the mock cache object does not hit the database as is needed diff --git a/tests/session/extract_page_test.php b/tests/session/extract_page_test.php index f0d1cdb60e..88eb7b2c1a 100644 --- a/tests/session/extract_page_test.php +++ b/tests/session/extract_page_test.php @@ -12,7 +12,6 @@  */  require_once dirname(__FILE__) . '/../test_framework/phpbb_session_test_case.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_session_extract_page_test extends phpbb_session_test_case  { @@ -145,7 +144,7 @@ class phpbb_session_extract_page_test extends phpbb_session_test_case  	{  		global $symfony_request, $request, $phpbb_filesystem; -		$phpbb_filesystem = new \phpbb\filesystem(); +		$phpbb_filesystem = new \phpbb\filesystem\filesystem();  		$server['HTTP_HOST']			= 'localhost';  		$server['SERVER_NAME']			= 'localhost'; diff --git a/tests/session/garbage_collection_test.php b/tests/session/garbage_collection_test.php index 3fad81c68b..3dc591a328 100644 --- a/tests/session/garbage_collection_test.php +++ b/tests/session/garbage_collection_test.php @@ -12,7 +12,6 @@  */  require_once dirname(__FILE__) . '/../test_framework/phpbb_session_test_case.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_session_garbage_collection_test extends phpbb_session_test_case  { diff --git a/tests/session/session_key_test.php b/tests/session/session_key_test.php index bf3dfcaa3c..2499ea1d55 100644 --- a/tests/session/session_key_test.php +++ b/tests/session/session_key_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../test_framework/phpbb_session_test_case.php';  class phpbb_session_login_keys_test extends phpbb_session_test_case diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index 3e25286480..6f8b49122b 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -73,7 +73,7 @@ class phpbb_session_testable_factory  	public function get_session(\phpbb\db\driver\driver_interface $dbal)  	{  		// set up all the global variables used by session -		global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container; +		global $SID, $_SID, $db, $config, $cache, $request, $phpbb_container, $phpbb_root_path;  		$request = $this->request = new phpbb_mock_request(  			array(), @@ -81,10 +81,8 @@ class phpbb_session_testable_factory  			$this->cookies,  			$this->server_data  		); -		request_var(null, null, null, null, $request);  		$config = $this->config = new \phpbb\config\config($this->get_config_data()); -		set_config(null, null, null, $config);  		$db = $dbal; @@ -96,6 +94,8 @@ class phpbb_session_testable_factory  			'auth.provider.db',  			new phpbb_mock_auth_provider()  		); +		$phpbb_container->setParameter('core.environment', PHPBB_ENVIRONMENT); +		$phpbb_container->setParameter('core.cache_dir', $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/');  		$provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config);  		$provider_collection->add('auth.provider.db');  		$phpbb_container->set( diff --git a/tests/template/asset_test.php b/tests/template/asset_test.php new file mode 100644 index 0000000000..3d2fdd8959 --- /dev/null +++ b/tests/template/asset_test.php @@ -0,0 +1,49 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +use phpbb\template\asset; + +class phpbb_template_asset_test extends phpbb_test_case +{ +	public function set_path_data() +	{ +		return array( +			// array(phpbb_root_path, given path, expected path), +			array('.', 'foo/bar', 'foo/bar'), +			array('../', 'foo/bar', 'foo/bar'), +			array('./phpBB/', 'foo/bar', 'foo/bar'), +			array('../', __DIR__ . '/foo/bar', '../' . basename(dirname(dirname(__DIR__))) . '/tests/template/foo/bar'), +			array('./', __DIR__ . '/foo/bar', './tests/template/foo/bar'), +			array('./phpBB/', __DIR__ . '/foo/bar', 'tests/template/foo/bar'), +		); +	} + +	/** +	 * @dataProvider set_path_data +	 */ +	public function test_set_path($phpbb_root_path, $path, $expected) +	{ +		$path_helper = $this->getMockBuilder('\phpbb\path_helper') +			->disableOriginalConstructor() +			->setMethods(array()) +			->getMock(); + +		$path_helper->method('get_phpbb_root_path') +			->willReturn($phpbb_root_path); + +		$asset = new asset('', $path_helper, new phpbb\filesystem\filesystem()); + +		$asset->set_path($path, true); +		$this->assertEquals($expected, $asset->get_path()); +	} +} diff --git a/tests/template/includephp_test.php b/tests/template/includephp_test.php index fdddbef4f2..722e10e42d 100644 --- a/tests/template/includephp_test.php +++ b/tests/template/includephp_test.php @@ -39,8 +39,9 @@ class phpbb_template_includephp_test extends phpbb_template_template_test_case  	{  		global $phpbb_root_path; +		$filesystem = new \phpbb\filesystem\filesystem();  		$path_to_php = str_replace('\\', '/', dirname(__FILE__)) . '/templates/_dummy_include.php.inc'; -		$this->assertTrue(phpbb_is_absolute($path_to_php)); +		$this->assertTrue($filesystem->is_absolute_path($path_to_php));  		$template_text = "Path is absolute.\n<!-- INCLUDEPHP $path_to_php -->";  		$cache_dir = $phpbb_root_path . 'cache/'; diff --git a/tests/template/template_allfolder_test.php b/tests/template/template_allfolder_test.php index b4ad84e9c3..9a0a42fabd 100644 --- a/tests/template/template_allfolder_test.php +++ b/tests/template/template_allfolder_test.php @@ -28,13 +28,18 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case  		$defaults = $this->config_defaults();  		$config = new \phpbb\config\config(array_merge($defaults, $new_config)); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$this->user = $user; + +		$filesystem = new \phpbb\filesystem\filesystem();  		$path_helper = new \phpbb\path_helper(  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			$filesystem,  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			$phpEx @@ -51,9 +56,29 @@ class phpbb_template_allfolder_test extends phpbb_template_template_test_case  			)  		); +		$container = new phpbb_mock_container_builder(); +		$cache_path = $phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); +		$twig = new \phpbb\template\twig\environment( +			$config, +			$filesystem, +			$path_helper, +			$cache_path, +			$this->extension_manager, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		); +		$this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig)); +  		$this->template_path = $this->test_path . '/templates';  		$this->ext_template_path = 'tests/extension/ext/vendor4/bar/styles/all/template'; -		$this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, new \phpbb\template\context(), $this->extension_manager);  		$this->template->set_custom_style('all', array($this->template_path, $this->ext_template_path));  	}  } diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php index c415c969fe..e245c90aee 100644 --- a/tests/template/template_events_test.php +++ b/tests/template/template_events_test.php @@ -138,16 +138,39 @@ Zeta test event in all',  		$this->extension_manager = new phpbb_mock_filesystem_extension_manager(  			dirname(__FILE__) . "/datasets/$dataset/"  		); + +		$filesystem = new \phpbb\filesystem\filesystem();  		$path_helper = new \phpbb\path_helper(  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			new \phpbb\filesystem\filesystem(),  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			$phpEx  		); -		$this->template = new \phpbb\template\twig\twig($path_helper, $config, $user, new \phpbb\template\context, $this->extension_manager); + +		$container = new phpbb_mock_container_builder(); +		$cache_path = $phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); +		$twig = new \phpbb\template\twig\environment( +			$config, +			$filesystem, +			$path_helper, +			$cache_path, +			$this->extension_manager, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		); +		$this->template = new \phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user)), $this->extension_manager); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig)); +  		$this->template->set_custom_style(((!empty($style_names)) ? $style_names : 'silver'), array($this->template_path));  	}  } diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php index b025cd21d5..764652c9c2 100644 --- a/tests/template/template_includecss_test.php +++ b/tests/template/template_includecss_test.php @@ -15,6 +15,12 @@ require_once dirname(__FILE__) . '/template_test_case_with_tree.php';  class phpbb_template_template_includecss_test extends phpbb_template_template_test_case_with_tree  { +	/** @var \phpbb\path_helper */ +	protected $phpbb_path_helper; + +	/** @var string */ +	protected $parent_template_path; +  	protected function setup_engine(array $new_config = array())  	{  		global $phpbb_root_path, $phpEx, $user; @@ -22,11 +28,13 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te  		$defaults = $this->config_defaults();  		$config = new \phpbb\config\config(array_merge($defaults, $new_config)); +		$filesystem = new \phpbb\filesystem\filesystem(); +  		$this->phpbb_path_helper = new \phpbb\path_helper(  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			$filesystem,  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			$phpEx @@ -34,11 +42,32 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te  		$this->template_path = $this->test_path . '/templates';  		$this->parent_template_path = $this->test_path . '/parent_templates'; +		$container = new phpbb_mock_container_builder(); +		$cache_path = $phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); +		$twig = new \phpbb\template\twig\environment( +			$config, +			$filesystem, +			$this->phpbb_path_helper, +			$cache_path, +			null, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		);  		$this->template = new phpbb\template\twig\twig(  			$this->phpbb_path_helper,  			$config, -			$user, -			new phpbb\template\context(), +			$context, +			$twig, +			$cache_path, +			$this->user, +			array(new \phpbb\template\twig\extension($context, $this->user)),  			new phpbb_mock_extension_manager(  				dirname(__FILE__) . '/',  				array( @@ -50,6 +79,7 @@ class phpbb_template_template_includecss_test extends phpbb_template_template_te  				)  			)  		); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig));  		$this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path));  	} diff --git a/tests/template/template_parser_test.php b/tests/template/template_parser_test.php index d32fe78391..938b1bc8b8 100644 --- a/tests/template/template_parser_test.php +++ b/tests/template/template_parser_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/template_test_case.php';  class phpbb_template_template_parser_test extends phpbb_template_template_test_case diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 0bbfe3848d..63e7cb869a 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/template_test_case.php';  class phpbb_template_template_test extends phpbb_template_template_test_case @@ -130,6 +129,34 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1",  			),  			array( +				'loop_twig.html', +				array(), +				array(), +				array(), +				"noloop\nnoloop", +			), +			array( +				'loop_twig.html', +				array(), +				array('test_loop' => array(array())), +				array(), +				"loop\nloop", +			), +			array( +				'loop_twig.html', +				array(), +				array('test_loop' => array(array(), array()), 'test_loop.block' => array(array())), +				array(), +				"loop\nloop\nloop\nloop", +			), +			array( +				'loop_twig.html', +				array(), +				array('test_loop' => array(array(), array()), 'test_loop.block' => array(array()), 'block' => array(array(), array())), +				array(), +				"loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1", +			), +			array(  				'loop_vars.html',  				array(),  				array('test_loop' => array(array('VARIABLE' => 'x'))), @@ -151,6 +178,27 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner",  			),  			array( +				'loop_vars_twig.html', +				array(), +				array('test_loop' => array(array('VARIABLE' => 'x'))), +				array(), +				"first\n0 - a\nx - b\nset\nlast", +			), +			array( +				'loop_vars_twig.html', +				array(), +				array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y'))), +				array(), +				"first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast", +			), +			array( +				'loop_vars_twig.html', +				array(), +				array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'test_loop.inner' => array(array(), array())), +				array(), +				"first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner", +			), +			array(  				'loop_advanced.html',  				array(),  				array('test_loop' => array(array(), array(), array(), array(), array(), array(), array())), @@ -158,6 +206,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561",  			),  			array( +				'loop_advanced_twig.html', +				array(), +				array('test_loop' => array(array(), array(), array(), array(), array(), array(), array())), +				array(), +				"101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561", +			), +			array(  				'loop_nested2.html',  				array(),  				array('outer' => array(array(), array()), 'outer.middle' => array(array(), array())), @@ -165,6 +220,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"o0o1m01m11",  			),  			array( +				'loop_nested2_twig.html', +				array(), +				array('outer' => array(array(), array()), 'outer.middle' => array(array(), array())), +				array(), +				"o0o1m01m11", +			), +			array(  				'define.html',  				array(),  				array('test_loop' => array(array(), array(), array(), array(), array(), array(), array()), 'test' => array(array()), 'test.deep' => array(array()), 'test.deep.defines' => array(array())), @@ -244,6 +306,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				'',  			),  			array( +				'loop_vars_twig.html', +				array(), +				array('test_loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'test_loop.inner' => array(array(), array())), +				array('test_loop'), +				'', +			), +			array(  				'include_define_variable.html',  				array('VARIABLE' => 'variable.html'),  				array(), @@ -275,6 +344,15 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"noloop\nnoloop",  			),  			array( +				// Just like a regular loop but the name begins +				// with an underscore +				'loop_underscore_twig.html', +				array(), +				array(), +				array(), +				"noloop\nnoloop", +			), +			array(  				'lang.html',  				array(),  				array(), @@ -286,7 +364,7 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				array(),  				array(),  				array(), -				"Value'\n1 O'Clock\nValue\'\n1 O\'Clock", +				"Value'\n1 O'Clock\nValue\\x27\n1\\x20O\\x27Clock",  				array('VARIABLE' => "Value'", '1_VARIABLE' => "1 O'Clock"),  			),  			array( @@ -297,6 +375,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"top-level content",  			),  			array( +				'loop_nested_multilevel_ref_twig.html', +				array(), +				array(), +				array(), +				"top-level content", +			), +			array(  				'loop_nested_multilevel_ref.html',  				array(),  				array('outer' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'outer.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))), @@ -304,6 +389,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz",  			),  			array( +				'loop_nested_multilevel_ref_twig.html', +				array(), +				array('outer' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'outer.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))), +				array(), +				"top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz", +			), +			array(  				'loop_nested_deep_multilevel_ref.html',  				array(),  				array('outer' => array(array()), 'outer.middle' => array(array()), 'outer.middle.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))), @@ -311,6 +403,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz",  			),  			array( +				'loop_nested_deep_multilevel_ref_twig.html', +				array(), +				array('outer' => array(array()), 'outer.middle' => array(array()), 'outer.middle.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))), +				array(), +				"top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz", +			), +			array(  				'loop_size.html',  				array(),  				array('test_loop' => array(array()), 'empty_loop' => array()), @@ -318,6 +417,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop",  			),  			array( +				'loop_size_twig.html', +				array(), +				array('test_loop' => array(array()), 'empty_loop' => array()), +				array(), +				"nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop", +			), +			array(  				'loop_include.html',  				array(),  				array('test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1'))), @@ -325,6 +431,13 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"barbarbar1bar1",  			),  			array( +				'loop_include_twig.html', +				array(), +				array('test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1'))), +				array(), +				"barbarbar1bar1", +			), +			array(  				'loop_nested_include.html',  				array(),  				array( @@ -335,6 +448,17 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				"[bar|[bar|]][bar1|[bar1|[bar1|works]]]",  				array(),  			), +			array( +				'loop_nested_include_twig.html', +				array(), +				array( +					'test_loop' => array(array('foo' => 'bar'), array('foo' => 'bar1')), +					'test_loop.inner' => array(array('myinner' => 'works')), +				), +				array(), +				"[bar|[bar|]][bar1|[bar1|[bar1|works]]]", +				array(), +			),  			/* Does not pass with the current implementation.  			array(  				'loop_reuse.html', @@ -343,8 +467,15 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				array(),  				// Not entirely sure what should be outputted but the current output of "a" is most certainly wrong  				"a\nb\nc\nd", +			),*/ +			array( +				'loop_reuse_twig.html', +				array(), +				array('one' => array(array('VAR' => 'a'), array('VAR' => 'b')), 'one.one' => array(array('VAR' => 'c'), array('VAR' => 'd'))), +				array(), +				// Not entirely sure what should be outputted but the current output of "a" is most certainly wrong +				"a\nb\nc\nd",  			), -			*/  			array(  				'twig.html',  				array('VARIABLE' => 'FOObar',), @@ -359,6 +490,27 @@ class phpbb_template_template_test extends phpbb_template_template_test_case  				array(),  				'inner_value',  			), +			array( +				'loop_expressions.html', +				array(), +				array('loop' => array(array(),array(),array(),array(),array(),array()),), +				array(), +				'yesnononoyesnoyesnonoyesnono', +			), +			array( +				'loop_expressions_twig.html', +				array(), +				array('loop' => array(array(),array(),array(),array(),array(),array()),), +				array(), +				'yesnononoyesnoyesnonoyesnono', +			), +			array( +				'loop_expressions_twig2.html', +				array('loop' => array(array(),array(),array(),array(),array(),array()),), +				array(), +				array(), +				'yesnononoyesnoyesnonoyesnono', +			),  		);  	} diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php index 1250397401..e52d3b76dd 100644 --- a/tests/template/template_test_case.php +++ b/tests/template/template_test_case.php @@ -11,10 +11,9 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_template_template_test_case extends phpbb_test_case  { +	protected $lang;  	protected $template;  	protected $template_path;  	protected $user; @@ -24,6 +23,17 @@ class phpbb_template_template_test_case extends phpbb_test_case  	// Keep the contents of the cache for debugging?  	const PRESERVE_CACHE = true; +	static protected $language_reflection_lang; + +	static public function setUpBeforeClass() +	{ +		parent::setUpBeforeClass(); + +		$reflection = new ReflectionClass('\phpbb\language\language'); +		self::$language_reflection_lang = $reflection->getProperty('lang'); +		self::$language_reflection_lang->setAccessible(true); +	} +  	protected function display($handle)  	{  		ob_start(); @@ -65,20 +75,45 @@ class phpbb_template_template_test_case extends phpbb_test_case  		$defaults = $this->config_defaults();  		$config = new \phpbb\config\config(array_merge($defaults, $new_config)); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$this->lang = $lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$this->user = $user; + +		$filesystem = new \phpbb\filesystem\filesystem();  		$path_helper = new \phpbb\path_helper(  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			$filesystem,  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			$phpEx  		);  		$this->template_path = $this->test_path . '/templates'; -		$this->template = new \phpbb\template\twig\twig($path_helper, $config, $this->user, new \phpbb\template\context()); + +		$container = new phpbb_mock_container_builder(); +		$cache_path = $phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); +		$twig = new \phpbb\template\twig\environment( +			$config, +			$filesystem, +			$path_helper, +			$cache_path, +			null, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		); +		$this->template = new phpbb\template\twig\twig($path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig));  		$this->template->set_custom_style('tests', $this->template_path);  	} @@ -88,6 +123,10 @@ class phpbb_template_template_test_case extends phpbb_test_case  		$this->setup_engine();  		$this->template->clear_cache(); + +		global $phpbb_filesystem; + +		$phpbb_filesystem = new \phpbb\filesystem\filesystem();  	}  	protected function tearDown() @@ -121,12 +160,16 @@ class phpbb_template_template_test_case extends phpbb_test_case  		{  			foreach ($lang_vars as $name => $value)  			{ -				$this->user->lang[$name] = $value; +				self::$language_reflection_lang->setValue($this->lang, array_merge( +					self::$language_reflection_lang->getValue($this->lang), +					array($name => $value) +				));  			}  		}  		$expected = str_replace(array("\n", "\r", "\t"), '', $expected);  		$output = str_replace(array("\n", "\r", "\t"), '', $this->display('test')); +  		$this->assertEquals($expected, $output, "Testing $file");  	}  } diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php index 68ecc4b706..ff35d16120 100644 --- a/tests/template/template_test_case_with_tree.php +++ b/tests/template/template_test_case_with_tree.php @@ -22,11 +22,13 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat  		$defaults = $this->config_defaults();  		$config = new \phpbb\config\config(array_merge($defaults, $new_config)); +		$filesystem = new \phpbb\filesystem\filesystem(); +  		$this->phpbb_path_helper = new \phpbb\path_helper(  			new \phpbb\symfony_request(  				new phpbb_mock_request()  			), -			new \phpbb\filesystem(), +			$filesystem,  			$this->getMock('\phpbb\request\request'),  			$phpbb_root_path,  			$phpEx @@ -34,7 +36,27 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat  		$this->template_path = $this->test_path . '/templates';  		$this->parent_template_path = $this->test_path . '/parent_templates'; -		$this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $user, new phpbb\template\context()); + +		$container = new phpbb_mock_container_builder(); +		$cache_path = $phpbb_root_path . 'cache/twig'; +		$context = new \phpbb\template\context(); +		$loader = new \phpbb\template\twig\loader(new \phpbb\filesystem\filesystem(), ''); +		$twig = new \phpbb\template\twig\environment( +			$config, +			$filesystem, +			$this->phpbb_path_helper, +			$cache_path, +			null, +			$loader, +			array( +				'cache'			=> false, +				'debug'			=> false, +				'auto_reload'	=> true, +				'autoescape'	=> false, +			) +		); +		$this->template = new phpbb\template\twig\twig($this->phpbb_path_helper, $config, $context, $twig, $cache_path, $this->user, array(new \phpbb\template\twig\extension($context, $this->user))); +		$twig->setLexer(new \phpbb\template\twig\lexer($twig));  		$this->template->set_custom_style('tests', array($this->template_path, $this->parent_template_path));  	}  } diff --git a/tests/template/templates/loop_advanced_twig.html b/tests/template/templates/loop_advanced_twig.html new file mode 100644 index 0000000000..fd9fcae045 --- /dev/null +++ b/tests/template/templates/loop_advanced_twig.html @@ -0,0 +1,19 @@ +{% for test_loop_inner in test_loop %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0,-1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(1,1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0,1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(2,4) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(0,-7) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(-2,6) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} +x +{% for test_loop_inner in test_loop|subset(-2,-1) %}{{ test_loop_inner.S_FIRST_ROW }}{{ test_loop_inner.S_ROW_COUNT }}{{ test_loop_inner.S_LAST_ROW }}{% endfor %} diff --git a/tests/template/templates/loop_expressions.html b/tests/template/templates/loop_expressions.html index 6bff53f388..ddb9fd52fa 100644 --- a/tests/template/templates/loop_expressions.html +++ b/tests/template/templates/loop_expressions.html @@ -1,11 +1,11 @@  <!-- BEGIN loop --> -<!-- IF loop.S_ROW_NUM is even by 4 -->on<!-- ELSE -->off<!-- ENDIF --> +<!-- IF loop.S_ROW_NUM is divisible by(4) -->yes<!-- ELSE -->no<!-- ENDIF -->  <!-- END loop -->  <!-- BEGIN loop --> -<!-- IF loop.S_ROW_NUM is odd by 3 -->on<!-- ELSE -->off<!-- ENDIF --> +<!-- IF loop.S_ROW_NUM is divisible by(3) -->yes<!-- ELSE -->no<!-- ENDIF -->  <!-- END loop --> diff --git a/tests/template/templates/loop_expressions_twig.html b/tests/template/templates/loop_expressions_twig.html new file mode 100644 index 0000000000..5ca8cc3601 --- /dev/null +++ b/tests/template/templates/loop_expressions_twig.html @@ -0,0 +1,11 @@ +{% for loop_inner in loop %} + +{% if loop_inner.S_ROW_NUM is divisible by(4) %}yes{% else %}no{% endif %} + +{% endfor %} + +{% for loop_inner in loop %} + +{% if loop_inner.S_ROW_NUM is divisible by(3) %}yes{% else %}no{% endif %} + +{% endfor %} diff --git a/tests/template/templates/loop_expressions_twig2.html b/tests/template/templates/loop_expressions_twig2.html new file mode 100644 index 0000000000..16159ead4c --- /dev/null +++ b/tests/template/templates/loop_expressions_twig2.html @@ -0,0 +1,11 @@ +{% for loop_inner in loop %} + +{% if loop.index0 is divisible by(4) %}yes{% else %}no{% endif %} + +{% endfor %} + +{% for loop_inner in loop %} + +{% if loop.index0 is divisible by(3) %}yes{% else %}no{% endif %} + +{% endfor %} diff --git a/tests/template/templates/loop_include1_twig.html b/tests/template/templates/loop_include1_twig.html new file mode 100644 index 0000000000..2ff9f61b02 --- /dev/null +++ b/tests/template/templates/loop_include1_twig.html @@ -0,0 +1 @@ +{{ test_loop_inner.foo }} diff --git a/tests/template/templates/loop_include_twig.html b/tests/template/templates/loop_include_twig.html new file mode 100644 index 0000000000..1a534e2dbc --- /dev/null +++ b/tests/template/templates/loop_include_twig.html @@ -0,0 +1,4 @@ +{% for test_loop_inner in test_loop %} +	{{ test_loop_inner.foo }} +	{% INCLUDE 'loop_include1_twig.html' %} +{% endfor %} diff --git a/tests/template/templates/loop_nested2_twig.html b/tests/template/templates/loop_nested2_twig.html new file mode 100644 index 0000000000..cf802dc69f --- /dev/null +++ b/tests/template/templates/loop_nested2_twig.html @@ -0,0 +1,6 @@ +{% for outer_inner in outer %} +	o{{ outer_inner.S_ROW_COUNT }} +	{% for middle in outer_inner.middle %} +		m{{ middle.S_ROW_COUNT }}{{ outer_inner.S_ROW_COUNT }} +	{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html b/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html new file mode 100644 index 0000000000..9bc68e6e2e --- /dev/null +++ b/tests/template/templates/loop_nested_deep_multilevel_ref_twig.html @@ -0,0 +1,13 @@ +top-level content +{% for outer_inner in outer %} +	outer +	{% for middle in outer_inner.middle %} +		{{ middle.S_BLOCK_NAME }} +		{% for inner in middle.inner %} +			inner {{ inner.VARIABLE }} +			{% if inner.S_FIRST_ROW %} +				first row of {{ inner.S_NUM_ROWS }} in {{ inner.S_BLOCK_NAME }} +			{% endif %} +		{% endfor %} +	{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_nested_include1_twig.html b/tests/template/templates/loop_nested_include1_twig.html new file mode 100644 index 0000000000..4c2ebb5f15 --- /dev/null +++ b/tests/template/templates/loop_nested_include1_twig.html @@ -0,0 +1,5 @@ +[{{ test_loop_inner.foo }}| +{% for inner in test_loop_inner.inner %} +	[{{ test_loop_inner.foo }}| +	{{ inner.myinner }}] +{% endfor %}] diff --git a/tests/template/templates/loop_nested_include_twig.html b/tests/template/templates/loop_nested_include_twig.html new file mode 100644 index 0000000000..c92ac922d1 --- /dev/null +++ b/tests/template/templates/loop_nested_include_twig.html @@ -0,0 +1,4 @@ +{% for test_loop_inner in test_loop %} +	[{{ test_loop_inner.foo }} +	|{% INCLUDE 'loop_nested_include1_twig.html' %}] +{% endfor %} diff --git a/tests/template/templates/loop_nested_multilevel_ref_twig.html b/tests/template/templates/loop_nested_multilevel_ref_twig.html new file mode 100644 index 0000000000..336a57d0bc --- /dev/null +++ b/tests/template/templates/loop_nested_multilevel_ref_twig.html @@ -0,0 +1,10 @@ +top-level content +{% for outer_inner in outer %} +	outer {{ outer_inner.VARIABLE }} +	{% for inner in outer_inner.inner %} +		inner {{ inner.VARIABLE }} +		{% if inner.S_FIRST_ROW %} +			first row +		{% endif %} +	{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_nested_twig.html b/tests/template/templates/loop_nested_twig.html new file mode 100644 index 0000000000..b294226b3a --- /dev/null +++ b/tests/template/templates/loop_nested_twig.html @@ -0,0 +1,6 @@ +{% for outer_inner in outer %} +outer - {{ outer_inner.S_ROW_COUNT }}{% if outer_inner.VARIABLE %} - {{ outer_inner.VARIABLE }}{% endif %}{% if TEST_MORE %}[{{ outer_inner.S_BLOCK_NAME }}|{{ outer_inner.S_NUM_ROWS }}]{% endif %} +{% for middle in outer_inner.middle %} +middle - {{ middle.S_ROW_COUNT }}{% if middle.VARIABLE %} - {{ middle.VARIABLE }}{% endif %}{% if TEST_MORE %}[{{ middle.S_BLOCK_NAME }}|{{ middle.S_NUM_ROWS }}]{% endif %} +{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_reuse_twig.html b/tests/template/templates/loop_reuse_twig.html new file mode 100644 index 0000000000..67452a737f --- /dev/null +++ b/tests/template/templates/loop_reuse_twig.html @@ -0,0 +1,6 @@ +{% for one_inner in one %} +	{{ one_inner.VAR }} +	{% for one_one_inner in one_inner.one %} +		{{ one_one_inner.VAR }} +	{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_size_twig.html b/tests/template/templates/loop_size_twig.html new file mode 100644 index 0000000000..f6d2571e11 --- /dev/null +++ b/tests/template/templates/loop_size_twig.html @@ -0,0 +1,39 @@ +{% if nonexistent_loop|length %} +nonexistent +{% endif %} + +{% if nonexistent_loop|length == 0 %} +nonexistent = 0 +{% endif %} + +{% if ! nonexistent_loop|length %} +! nonexistent +{% endif %} + +{% if empty_loop|length %} +empty +{% endif %} + +{% if empty_loop|length == 0 %} +empty = 0 +{% endif %} + +{% if ! empty_loop|length %} +! empty +{% endif %} + +{% if test_loop|length %} +loop +{% endif %} + +{% if test_loop|length == 0 %} +loop = 0 +{% endif %} + +{% if ! test_loop|length %} +! loop +{% endif %} + +{% for test_loop_inner in test_loop %} +in loop +{% endfor %} diff --git a/tests/template/templates/loop_twig.html b/tests/template/templates/loop_twig.html new file mode 100644 index 0000000000..fb24f331b3 --- /dev/null +++ b/tests/template/templates/loop_twig.html @@ -0,0 +1,21 @@ +{% for test_loop_inner in test_loop %} +loop +{% else %} +noloop +{% endfor %} + +{% if test_loop|length %} +loop +{% else %} +noloop +{% endif %} + +{% if test_loop|length == 2 %} +loop +{% endif %} + +{% for test_loop_inner in test_loop %} +{% for block_inner in block %} +loop#{{ test_loop_inner.S_ROW_COUNT }}-block#{{ block_inner.S_ROW_COUNT }} +{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_underscore_twig.html b/tests/template/templates/loop_underscore_twig.html new file mode 100644 index 0000000000..44b095c882 --- /dev/null +++ b/tests/template/templates/loop_underscore_twig.html @@ -0,0 +1,21 @@ +{% for _underscore_loop_inner in _underscore_loop %} +loop +{% else %} +noloop +{% endfor %} + +{% if _underscore_loop|length %} +loop +{% else %} +noloop +{% endif %} + +{% if _underscore_loop|length == 2 %} +loop +{% endif %} + +{% for _underscore_loop_inner in _underscore_loop %} +{% for block_inner in block %} +loop#{{ loop.S_ROW_COUNT }}-block#{{ block_inner.S_ROW_COUNT }} +{% endfor %} +{% endfor %} diff --git a/tests/template/templates/loop_vars_twig.html b/tests/template/templates/loop_vars_twig.html new file mode 100644 index 0000000000..af6c63d8e3 --- /dev/null +++ b/tests/template/templates/loop_vars_twig.html @@ -0,0 +1,13 @@ +{% for test_loop_inner in test_loop %} +{% if test_loop_inner.S_FIRST_ROW %}first{% endif %} +{{ test_loop_inner.S_ROW_NUM }} - a +{{ test_loop_inner.VARIABLE }} - b +{% if test_loop_inner.VARIABLE %}set{% endif %} +{% if test_loop_inner.S_LAST_ROW %} +last +{% endif %} +{% for inner_inner in test_loop_inner.inner %} +{{ inner_inner.S_ROW_NUM }} - c +{% if inner_inner.S_LAST_ROW and inner_inner.S_ROW_COUNT and inner_inner.S_NUM_ROWS %}last inner{% endif %} +{% endfor %} +{% endfor %} diff --git a/tests/test_framework/mock/phpbb_mock_null_installer_task.php b/tests/test_framework/mock/phpbb_mock_null_installer_task.php new file mode 100644 index 0000000000..c1b880d967 --- /dev/null +++ b/tests/test_framework/mock/phpbb_mock_null_installer_task.php @@ -0,0 +1,30 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_mock_null_installer_task extends \phpbb\install\task_base +{ +	public function run() +	{ + +	} + +	static public function get_step_count() +	{ +		return 0; +	} + +	public function get_task_lang_name() +	{ +		return ''; +	} +} diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index fc1a3632f4..b7386e9a3e 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -58,7 +58,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test  		$setup_extensions = static::setup_extensions(); -		$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx); +		$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx);  		$finder->core_path('phpbb/db/migration/data/');  		if (!empty($setup_extensions))  		{ @@ -76,8 +76,11 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test  			global $table_prefix; -			$db = new \phpbb\db\driver\sqlite(); -			$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); +			$db = new \phpbb\db\driver\sqlite3(); +			$factory = new \phpbb\db\tools\factory(); +			$db_tools = $factory->get($db, true); + +			$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);  			file_put_contents(self::$schema_file, json_encode($schema_generator->get_schema()));  		} diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php index 3b5bab749e..147029d699 100644 --- a/tests/test_framework/phpbb_database_test_connection_manager.php +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php';  require_once dirname(__FILE__) . '/phpbb_database_connection_odbc_pdo_wrapper.php';  class phpbb_database_test_connection_manager @@ -56,7 +55,6 @@ class phpbb_database_test_connection_manager  		switch ($this->dbms['PDO'])  		{ -			case 'sqlite2':  			case 'sqlite':	// SQLite3 driver  				$dsn .= $this->config['dbhost'];  			break; @@ -194,7 +192,6 @@ class phpbb_database_test_connection_manager  	{  		switch ($this->config['dbms'])  		{ -			case 'phpbb\db\driver\sqlite':  			case 'phpbb\db\driver\sqlite3':  				$this->connect();  				// Drop all of the tables @@ -270,12 +267,6 @@ class phpbb_database_test_connection_manager  				$sql = 'SHOW TABLES';  			break; -			case 'phpbb\db\driver\sqlite': -				$sql = 'SELECT name -					FROM sqlite_master -					WHERE type = "table"'; -			break; -  			case 'phpbb\db\driver\sqlite3':  				$sql = 'SELECT name  					FROM sqlite_master @@ -351,10 +342,13 @@ class phpbb_database_test_connection_manager  		if (file_exists($filename))  		{ +			global $phpbb_root_path; +  			$queries = file_get_contents($filename); -			$sql = phpbb_remove_comments($queries); -			$sql = split_sql_file($sql, $this->dbms['DELIM']); +			$db_helper = new \phpbb\install\helper\database(new \phpbb\filesystem\filesystem(), $phpbb_root_path); +			$sql = $db_helper->remove_comments($queries); +			$sql = $db_helper->split_sql_file($sql, $this->dbms['DELIM']);  			foreach ($sql as $query)  			{ @@ -372,16 +366,20 @@ class phpbb_database_test_connection_manager  		{  			global $phpbb_root_path, $phpEx, $table_prefix; -			$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx); +			$finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx);  			$classes = $finder->core_path('phpbb/db/migration/data/')  				->get_classes(); -			$db = new \phpbb\db\driver\sqlite(); -			$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix); +			$db = new \phpbb\db\driver\sqlite3(); +			$factory = new \phpbb\db\tools\factory(); +			$db_tools = $factory->get($db, true); + +			$schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);  			$db_table_schema = $schema_generator->get_schema();  		} -		$db_tools = new \phpbb\db\tools($db, true); +		$factory = new \phpbb\db\tools\factory(); +		$db_tools = $factory->get($db, true);  		foreach ($db_table_schema as $table_name => $table_data)  		{  			$queries = $db_tools->sql_create_table( @@ -448,11 +446,6 @@ class phpbb_database_test_connection_manager  				'DELIM'			=> ';',  				'PDO'			=> 'pgsql',  			), -			'phpbb\db\driver\sqlite'		=> array( -				'SCHEMA'		=> 'sqlite', -				'DELIM'			=> ';', -				'PDO'			=> 'sqlite2', -			),  			'phpbb\db\driver\sqlite3'		=> array(  				'SCHEMA'		=> 'sqlite',  				'DELIM'			=> ';', diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 8107e45dc7..20b89aba4e 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -12,13 +12,15 @@  */  use Symfony\Component\BrowserKit\CookieJar; -require_once __DIR__ . '/../../phpBB/includes/functions_install.php'; +require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php';  class phpbb_functional_test_case extends phpbb_test_case  { +	/** @var \Goutte\Client */  	static protected $client;  	static protected $cookieJar;  	static protected $root_url; +	static protected $install_success = false;  	protected $cache = null;  	protected $db = null; @@ -77,13 +79,15 @@ class phpbb_functional_test_case extends phpbb_test_case  	{  		parent::setUp(); +		if (!self::$install_success) +		{ +			$this->fail('Installing phpBB has failed.'); +		} +  		$this->bootstrap();  		self::$cookieJar = new CookieJar;  		self::$client = new Goutte\Client(array(), null, self::$cookieJar); -		// Reset the curl handle because it is 0 at this point and not a valid -		// resource -		self::$client->getClient()->getCurlMulti()->reset(true);  		// Clear the language array so that things  		// that were added in other tests are gone @@ -169,7 +173,7 @@ class phpbb_functional_test_case extends phpbb_test_case  	*/  	static public function get_content()  	{ -		return self::$client->getResponse()->getContent(); +		return (string) self::$client->getResponse()->getContent();  	}  	// bootstrap, called after board is set up @@ -205,6 +209,12 @@ class phpbb_functional_test_case extends phpbb_test_case  	{  		if (!$this->cache)  		{ +			global $phpbb_container, $phpbb_root_path; + +			$phpbb_container = new phpbb_mock_container_builder(); +			$phpbb_container->setParameter('core.environment', PHPBB_ENVIRONMENT); +			$phpbb_container->setParameter('core.cache_dir', $phpbb_root_path . 'cache/' . PHPBB_ENVIRONMENT . '/'); +  			$this->cache = new \phpbb\cache\driver\file;  		} @@ -226,7 +236,8 @@ class phpbb_functional_test_case extends phpbb_test_case  		$config = new \phpbb\config\config(array());  		$db = $this->get_db(); -		$db_tools = new \phpbb\db\tools($db); +		$factory = new \phpbb\db\tools\factory(); +		$db_tools = $factory->get($db);  		$container = new phpbb_mock_container_builder();  		$migrator = new \phpbb\db\migrator( @@ -243,14 +254,12 @@ class phpbb_functional_test_case extends phpbb_test_case  		);  		$container->set('migrator', $migrator);  		$container->set('dispatcher', new phpbb_mock_event_dispatcher()); -		$user = new \phpbb\user('\phpbb\datetime');  		$extension_manager = new \phpbb\extension\manager(  			$container,  			$db,  			$config, -			new phpbb\filesystem(), -			$user, +			new phpbb\filesystem\filesystem(),  			self::$config['table_prefix'] . 'ext',  			dirname(__FILE__) . '/',  			$phpEx, @@ -282,120 +291,111 @@ class phpbb_functional_test_case extends phpbb_test_case  			}  		} -		self::$cookieJar = new CookieJar; -		self::$client = new Goutte\Client(array(), null, self::$cookieJar); -		// Set client manually so we can increase the cURL timeout -		self::$client->setClient(new Guzzle\Http\Client('', array( -			Guzzle\Http\Client::DISABLE_REDIRECTS	=> true, -			'curl.options'	=> array( -				CURLOPT_TIMEOUT	=> 120, -			), -		))); - -		// Reset the curl handle because it is 0 at this point and not a valid -		// resource -		self::$client->getClient()->getCurlMulti()->reset(true); +		$container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +		$container = $container_builder +			->with_environment('installer') +			->without_extensions() +			->without_cache() +			->with_custom_parameters([ +				'core.disable_super_globals' => false, +				'installer.create_config_file.options' => [ +					'debug' => true, +					'environment' => 'test', +				], +				'cache.driver.class' => 'phpbb\cache\driver\file' +			]) +			->without_compiled_container() +			->get_container(); + +		$container->register('installer.install_finish.notify_user')->setSynthetic(true); +		$container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task()); +		$container->compile(); + +		$language = $container->get('language'); +		$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting')); + +		$iohandler_factory = $container->get('installer.helper.iohandler_factory'); +		$iohandler_factory->set_environment('cli'); +		$iohandler = $iohandler_factory->get();  		$parseURL = parse_url(self::$config['phpbb_functional_url']); -		$crawler = self::request('GET', 'install/index.php?mode=install&language=en'); -		self::assertContains('Welcome to Installation', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(); - -		// install/index.php?mode=install&sub=requirements -		$crawler = self::submit($form); -		self::assertContains('Installation compatibility', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(); - -		// install/index.php?mode=install&sub=database -		$crawler = self::submit($form); -		self::assertContains('Database configuration', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(array( -			// Installer uses 3.0-style dbms name -			'dbms'			=> str_replace('phpbb\db\driver\\', '',  self::$config['dbms']), -			'dbhost'		=> self::$config['dbhost'], -			'dbport'		=> self::$config['dbport'], -			'dbname'		=> self::$config['dbname'], -			'dbuser'		=> self::$config['dbuser'], -			'dbpasswd'		=> self::$config['dbpasswd'], -			'table_prefix'	=> self::$config['table_prefix'], -		)); +		$output = new \Symfony\Component\Console\Output\NullOutput(); +		$style = new \Symfony\Component\Console\Style\SymfonyStyle( +			new \Symfony\Component\Console\Input\ArrayInput(array()), +			$output +		); +		$iohandler->set_style($style, $output); + +		$installer = $container->get('installer.installer.install'); +		$installer->set_iohandler($iohandler); + +		// Set data +		$iohandler->set_input('admin_name', 'admin'); +		$iohandler->set_input('admin_pass1', 'adminadmin'); +		$iohandler->set_input('admin_pass2', 'adminadmin'); +		$iohandler->set_input('board_email', 'nobody@example.com'); +		$iohandler->set_input('submit_admin', 'submit'); + +		$iohandler->set_input('default_lang', 'en'); +		$iohandler->set_input('board_name', 'yourdomain.com'); +		$iohandler->set_input('board_description', 'A short text to describe your forum'); +		$iohandler->set_input('submit_board', 'submit'); + +		$iohandler->set_input('dbms', str_replace('phpbb\db\driver\\', '',  self::$config['dbms'])); +		$iohandler->set_input('dbhost', self::$config['dbhost']); +		$iohandler->set_input('dbport', self::$config['dbport']); +		$iohandler->set_input('dbuser', self::$config['dbuser']); +		$iohandler->set_input('dbpasswd', self::$config['dbpasswd']); +		$iohandler->set_input('dbname', self::$config['dbname']); +		$iohandler->set_input('table_prefix', self::$config['table_prefix']); +		$iohandler->set_input('submit_database', 'submit'); + +		$iohandler->set_input('email_enable', true); +		$iohandler->set_input('smtp_delivery', '1'); +		$iohandler->set_input('smtp_host', 'nxdomain.phpbb.com'); +		$iohandler->set_input('smtp_auth', 'PLAIN'); +		$iohandler->set_input('smtp_user', 'nxuser'); +		$iohandler->set_input('smtp_pass', 'nxpass'); +		$iohandler->set_input('submit_email', 'submit'); + +		$iohandler->set_input('cookie_secure', '0'); +		$iohandler->set_input('server_protocol', '0'); +		$iohandler->set_input('force_server_vars', $parseURL['scheme'] . '://'); +		$iohandler->set_input('server_name', $parseURL['host']); +		$iohandler->set_input('server_port', isset($parseURL['port']) ? (int) $parseURL['port'] : 80); +		$iohandler->set_input('script_path', $parseURL['path']); +		$iohandler->set_input('submit_server', 'submit'); + +		$installer->run(); -		// install/index.php?mode=install&sub=database -		$crawler = self::submit($form); -		self::assertContains('Successful connection', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(); +		copy($config_file, $config_file_test); -		// install/index.php?mode=install&sub=administrator -		$crawler = self::submit($form); -		self::assertContains('Administrator configuration', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(array( -			'default_lang'	=> 'en', -			'admin_name'	=> 'admin', -			'admin_pass1'	=> 'adminadmin', -			'admin_pass2'	=> 'adminadmin', -			'board_email'	=> 'nobody@example.com', -		)); +		self::$install_success = true; -		// install/index.php?mode=install&sub=administrator -		$crawler = self::submit($form); -		self::assertContains('Tests passed', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(); - -		// We have to skip install/index.php?mode=install&sub=config_file -		// because that step will create a config.php file if phpBB has the -		// permission to do so. We have to create the config file on our own -		// in order to get the DEBUG constants defined. -		$config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true); -		$config_created = file_put_contents($config_file, $config_php_data) !== false; -		if (!$config_created) +		if (file_exists($phpbb_root_path . 'store/install_config.php'))  		{ -			self::markTestSkipped("Could not write $config_file file."); +			self::$install_success = false; +			@unlink($phpbb_root_path . 'store/install_config.php');  		} -		// We also have to create a install lock that is normally created by -		// the installer. The file will be removed by the final step of the -		// installer. -		$install_lock_file = $phpbb_root_path . 'cache/install_lock'; -		$lock_created = file_put_contents($install_lock_file, '') !== false; -		if (!$lock_created) +		if (file_exists($phpbb_root_path . 'cache/install_lock'))  		{ -			self::markTestSkipped("Could not create $lock_created file."); +			@unlink($phpbb_root_path . 'cache/install_lock');  		} -		@chmod($install_lock_file, 0666); - -		// install/index.php?mode=install&sub=advanced -		$form_data = $form->getValues(); -		unset($form_data['submit']); - -		$crawler = self::request('POST', 'install/index.php?mode=install&sub=advanced', $form_data); -		self::assertContains('The settings on this page are only necessary to set if you know that you require something different from the default.', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(array( -			'email_enable'		=> true, -			'smtp_delivery'		=> true, -			'smtp_host'			=> 'nxdomain.phpbb.com', -			'smtp_auth'			=> 'PLAIN', -			'smtp_user'			=> 'nxuser', -			'smtp_pass'			=> 'nxpass', -			'cookie_secure'		=> false, -			'force_server_vars'	=> false, -			'server_protocol'	=> $parseURL['scheme'] . '://', -			'server_name'		=> 'localhost', -			'server_port'		=> isset($parseURL['port']) ? (int) $parseURL['port'] : 80, -			'script_path'		=> $parseURL['path'], -		)); -		// install/index.php?mode=install&sub=create_table -		$crawler = self::submit($form); -		self::assertContains('The database tables used by phpBB', $crawler->filter('#main')->text()); -		self::assertContains('have been created and populated with some initial data.', $crawler->filter('#main')->text()); -		$form = $crawler->selectButton('submit')->form(); +		global $phpbb_container; +		$phpbb_container->reset(); -		// install/index.php?mode=install&sub=final -		$crawler = self::submit($form); -		self::assertContains('You have successfully installed', $crawler->text()); +		$blacklist = ['phpbb_class_loader_mock', 'phpbb_class_loader_ext', 'phpbb_class_loader']; -		copy($config_file, $config_file_test); +		foreach (array_keys($GLOBALS) as $key) +		{ +			if (is_object($GLOBALS[$key]) && !in_array($key, $blacklist, true)) +			{ +				unset($GLOBALS[$key]); +			} +		}  	}  	public function install_ext($extension) @@ -490,7 +490,7 @@ class phpbb_functional_test_case extends phpbb_test_case  			));  			$db->sql_query($sql); -			if ($style_path != 'prosilver' && $style_path != 'subsilver2') +			if ($style_path != 'prosilver')  			{  				@mkdir($phpbb_root_path . 'styles/' . $style_path, 0777);  				@mkdir($phpbb_root_path . 'styles/' . $style_path . '/template', 0777); @@ -529,7 +529,7 @@ class phpbb_functional_test_case extends phpbb_test_case  			$db->sql_query('DELETE FROM ' . STYLES_TEMPLATE_TABLE . ' WHERE template_id = ' . $style_id);  			$db->sql_query('DELETE FROM ' . STYLES_THEME_TABLE . ' WHERE theme_id = ' . $style_id); -			if ($style_path != 'prosilver' && $style_path != 'subsilver2') +			if ($style_path != 'prosilver')  			{  				@rmdir($phpbb_root_path . 'styles/' . $style_path . '/template');  				@rmdir($phpbb_root_path . 'styles/' . $style_path); @@ -571,7 +571,7 @@ class phpbb_functional_test_case extends phpbb_test_case  		}  		$cache = new phpbb_mock_null_cache; -		$cache_driver = new \phpbb\cache\driver\null(); +		$cache_driver = new \phpbb\cache\driver\dummy();  		$phpbb_container = new phpbb_mock_container_builder();  		$phpbb_container->set('cache.driver', $cache_driver);  		$phpbb_notifications = new phpbb_mock_notification_manager(); @@ -585,8 +585,7 @@ class phpbb_functional_test_case extends phpbb_test_case  		{  			require_once(__DIR__ . '/../../phpBB/includes/functions_user.php');  		} -		set_config(null, null, null, $config); -		set_config_count(null, null, null, $config); +  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher();  		$passwords_manager = $this->get_passwords_manager(); @@ -612,13 +611,16 @@ class phpbb_functional_test_case extends phpbb_test_case  		$db = $this->get_db();  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$auth = $this->getMock('\phpbb\auth\auth');  		$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);  		$cache = new phpbb_mock_null_cache; -		$cache_driver = new \phpbb\cache\driver\null(); +		$cache_driver = new \phpbb\cache\driver\dummy();  		$phpbb_container = new phpbb_mock_container_builder();  		$phpbb_container->set('cache.driver', $cache_driver);  		$phpbb_container->set('notification_manager', new phpbb_mock_notification_manager()); @@ -651,13 +653,16 @@ class phpbb_functional_test_case extends phpbb_test_case  		$db = $this->get_db();  		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); -		$user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime')); +		$user = $this->getMock('\phpbb\user', array(), array( +			new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)), +			'\phpbb\datetime' +		));  		$auth = $this->getMock('\phpbb\auth\auth');  		$phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);  		$cache = new phpbb_mock_null_cache; -		$cache_driver = new \phpbb\cache\driver\null(); +		$cache_driver = new \phpbb\cache\driver\dummy();  		$phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');  		$phpbb_container  			->expects($this->any()) @@ -856,7 +861,7 @@ class phpbb_functional_test_case extends phpbb_test_case  	static public function assert_response_html($status_code = 200)  	{  		// Any output before the doc type means there was an error -		$content = self::$client->getResponse()->getContent(); +		$content = self::get_content();  		self::assertNotContains('[phpBB Debug]', $content);  		self::assertStringStartsWith('<!DOCTYPE', trim($content), 'Output found before DOCTYPE specification.'); @@ -877,7 +882,7 @@ class phpbb_functional_test_case extends phpbb_test_case  	static public function assert_response_xml($status_code = 200)  	{  		// Any output before the xml opening means there was an error -		$content = self::$client->getResponse()->getContent(); +		$content = self::get_content();  		self::assertNotContains('[phpBB Debug]', $content);  		self::assertStringStartsWith('<?xml', trim($content), 'Output found before XML specification.'); @@ -948,8 +953,7 @@ class phpbb_functional_test_case extends phpbb_test_case  	*/  	public function assert_checkbox_is_unchecked($crawler, $name, $message = '')  	{ -		$this->assertSame( -			'', +		$this->assertNull(  			$this->assert_find_one_checkbox($crawler, $name)->attr('checked'),  			$message ?: "Failed asserting that checkbox $name is unchecked."  		); diff --git a/tests/test_framework/phpbb_session_test_case.php b/tests/test_framework/phpbb_session_test_case.php index 1bf0277fe0..b3d7780d14 100644 --- a/tests/test_framework/phpbb_session_test_case.php +++ b/tests/test_framework/phpbb_session_test_case.php @@ -11,7 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  require_once dirname(__FILE__) . '/../session/testable_factory.php';  require_once dirname(__FILE__) . '/../session/testable_facade.php'; @@ -34,7 +33,7 @@ abstract class phpbb_session_test_case extends phpbb_database_test_case  		$symfony_request = new \phpbb\symfony_request(  			new phpbb_mock_request()  		); -		$phpbb_filesystem = new \phpbb\filesystem(); +		$phpbb_filesystem = new \phpbb\filesystem\filesystem();  		$phpbb_path_helper = new \phpbb\path_helper(  			$symfony_request,  			$phpbb_filesystem, diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index dee70ad016..7fb9a740b8 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -11,6 +11,8 @@  *  */ +use Symfony\Component\DependencyInjection\ContainerInterface; +  class phpbb_test_case_helpers  {  	protected $expectedTriggerError = false; @@ -120,17 +122,6 @@ class phpbb_test_case_helpers  				'dbpasswd'	=> '',  			));  		} -		else if (extension_loaded('sqlite')) -		{ -			$config = array_merge($config, array( -				'dbms'		=> 'phpbb\db\driver\sqlite', -				'dbhost'	=> dirname(__FILE__) . '/../phpbb_unit_tests.sqlite2', // filename -				'dbport'	=> '', -				'dbname'	=> '', -				'dbuser'	=> '', -				'dbpasswd'	=> '', -			)); -		}  		if (isset($_SERVER['PHPBB_TEST_CONFIG']))  		{ @@ -298,4 +289,295 @@ class phpbb_test_case_helpers  			}  		}  	} + +	/** +	* Set working instances of the text_formatter.* services +	* +	* If no container is passed, the global $phpbb_container will be used and/or +	* created if applicable +	* +	* @param  ContainerInterface $container   Service container +	* @param  string             $fixture     Path to the XML fixture +	* @param  string             $styles_path Path to the styles dir +	* @return ContainerInterface +	*/ +	public function set_s9e_services(ContainerInterface $container = null, $fixture = null, $styles_path = null) +	{ +		static $first_run; +		global $config, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx, $request, $user; + +		$cache_dir = __DIR__ . '/../tmp/'; + +		// Remove old cache files on first run +		if (!isset($first_run)) +		{ +			$first_run = 1; + +			array_map('unlink', array_merge( +				glob($cache_dir . 'data_s9e_*'), +				glob($cache_dir . 's9e_*') +			)); +		} + +		if (!isset($container)) +		{ +			if (!isset($phpbb_container)) +			{ +				$phpbb_container = new phpbb_mock_container_builder; +			} + +			$container = $phpbb_container; +		} + +		if (!isset($fixture)) +		{ +			$fixture = __DIR__ . '/../text_formatter/s9e/fixtures/default_formatting.xml'; +		} + +		if (!isset($styles_path)) +		{ +			$styles_path = $phpbb_root_path . 'styles/'; +		} + +		$dataset = new DOMDocument; +		$dataset->load($fixture); + +		$tables = array( +			'phpbb_bbcodes' => array(), +			'phpbb_smilies' => array(), +			'phpbb_styles'  => array(), +			'phpbb_words'   => array() +		); +		foreach ($dataset->getElementsByTagName('table') as $table) +		{ +			$name = $table->getAttribute('name'); +			$columns = array(); + +			foreach ($table->getElementsByTagName('column') as $column) +			{ +				$columns[] = $column->textContent; +			} + +			foreach ($table->getElementsByTagName('row') as $row) +			{ +				$values = array(); + +				foreach ($row->getElementsByTagName('value') as $value) +				{ +					$values[] = $value->textContent; +				} + +				$tables[$name][] = array_combine($columns, $values); +			} +		} + +		// Set up a default style if there's none set +		if (empty($tables['phpbb_styles'])) +		{ +			$tables['phpbb_styles'][] = array( +				'style_id' => 1, +				'style_path' => 'prosilver', +				'bbcode_bitfield' => 'kNg=' +			); +		} + +		// Mock the DAL, make it return data from the fixture +		$mb = $this->test_case->getMockBuilder('phpbb\\textformatter\\data_access'); +		$mb->setMethods(array('get_bbcodes', 'get_censored_words', 'get_smilies', 'get_styles')); +		$mb->setConstructorArgs(array( +			$this->test_case->getMock('phpbb\\db\\driver\\driver'), +			'phpbb_bbcodes', +			'phpbb_smilies', +			'phpbb_styles', +			'phpbb_words', +			$styles_path +		)); + +		$dal = $mb->getMock(); +		$container->set('text_formatter.data_access', $dal); + +		$dal->expects($this->test_case->any()) +		    ->method('get_bbcodes') +		    ->will($this->test_case->returnValue($tables['phpbb_bbcodes'])); +		$dal->expects($this->test_case->any()) +		    ->method('get_smilies') +		    ->will($this->test_case->returnValue($tables['phpbb_smilies'])); +		$dal->expects($this->test_case->any()) +		    ->method('get_styles') +		    ->will($this->test_case->returnValue($tables['phpbb_styles'])); +		$dal->expects($this->test_case->any()) +		    ->method('get_censored_words') +		    ->will($this->test_case->returnValue($tables['phpbb_words'])); + +		// Cache the parser and renderer with a key based on this method's arguments +		$cache = new \phpbb\cache\driver\file($cache_dir); +		$prefix = '_s9e_' . md5(serialize(func_get_args())); +		$cache_key_parser = $prefix . '_parser'; +		$cache_key_renderer = $prefix . '_renderer'; +		$container->set('cache.driver', $cache); + +		if (!$container->isFrozen()) +		{ +			$container->setParameter('cache.dir', $cache_dir); +		} + +		// Create a path_helper +		if (!$container->has('path_helper') || $container->getDefinition('path_helper')->isSynthetic()) +		{ +			$path_helper = $this->test_case->getMockBuilder('phpbb\\path_helper') +				->disableOriginalConstructor() +				->setMethods(array('get_web_root_path')) +				->getMock(); +			$path_helper->expects($this->test_case->any()) +				->method('get_web_root_path') +				->will($this->test_case->returnValue('phpBB/')); + +			$container->set('path_helper', $path_helper); +		} +		else +		{ +			$path_helper = $container->get('path_helper'); +		} + +		// Create an event dispatcher +		if ($container->has('dispatcher')) +		{ +			$dispatcher = $container->get('dispatcher'); +		} +		else if (isset($phpbb_dispatcher)) +		{ +			$dispatcher = $phpbb_dispatcher; +		} +		else +		{ +			$dispatcher = new phpbb_mock_event_dispatcher; +		} +		if (!isset($phpbb_dispatcher)) +		{ +			$phpbb_dispatcher = $dispatcher; +		} + +		// Set up the a minimum config +		if ($container->has('config')) +		{ +			$config = $container->get('config'); +		} +		elseif (!isset($config)) +		{ +			$config = new \phpbb\config\config(array()); +		} +		$default_config = array( +			'allow_nocensors'       => false, +			'allowed_schemes_links' => 'http,https,ftp', +			'script_path'           => '/phpbb', +			'server_name'           => 'localhost', +			'server_port'           => 80, +			'server_protocol'       => 'http://', +			'smilies_path'          => 'images/smilies', +		); +		foreach ($default_config as $config_name => $config_value) +		{ +			if (!isset($config[$config_name])) +			{ +				$config[$config_name] = $config_value; +			} +		} + +		// Create a fake request +		if (!isset($request)) +		{ +			$request = new phpbb_mock_request; +		} + +		// Create and register the text_formatter.s9e.factory service +		$factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $config, new \phpbb\textformatter\s9e\link_helper, $cache_dir, $cache_key_parser, $cache_key_renderer); +		$container->set('text_formatter.s9e.factory', $factory); + +		// Create a user if none was provided, and add the common lang strings +		if ($container->has('user')) +		{ +			$user = $container->get('user'); +		} +		else +		{ +			$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +			$lang = new \phpbb\language\language($lang_loader); + +			$user = $this->test_case->getMockBuilder('\phpbb\user') +					->setConstructorArgs(array($lang, '\phpbb\datetime')) +					->setMethods(array('format_date')) +					->getMock(); +			$user->expects($this->test_case->any()) +			     ->method('format_date') +			     ->will($this->test_case->returnCallback(__CLASS__ . '::format_date')); + +			$user->date_format = 'Y-m-d H:i:s'; +			$user->optionset('viewcensors', true); +			$user->optionset('viewflash', true); +			$user->optionset('viewimg', true); +			$user->optionset('viewsmilies', true); +			$user->timezone = new \DateTimeZone('UTC'); +			$container->set('user', $user); +		} +		$user->add_lang('common'); + +		if (!isset($user->style)) +		{ +			$user->style = array('style_id' => 1); +		} + +		// Create and register a quote_helper +		$quote_helper = new \phpbb\textformatter\s9e\quote_helper( +			$container->get('user'), +			$phpbb_root_path, +			$phpEx +		); +		$container->set('text_formatter.s9e.quote_helper', $quote_helper); + +		// Create and register the text_formatter.s9e.parser service and its alias +		$parser = new \phpbb\textformatter\s9e\parser( +			$cache, +			$cache_key_parser, +			$factory, +			$dispatcher +		); +		$container->set('text_formatter.parser', $parser); +		$container->set('text_formatter.s9e.parser', $parser); + +		// Create and register the text_formatter.s9e.renderer service and its alias +		$renderer = new \phpbb\textformatter\s9e\renderer( +			$cache, +			$cache_dir, +			$cache_key_renderer, +			$factory, +			$dispatcher +		); + +		// Calls configured in services.yml +		$auth = ($container->has('auth')) ? $container->get('auth') : new \phpbb\auth\auth; +		$renderer->configure_quote_helper($quote_helper); +		$renderer->configure_smilies_path($config, $path_helper); +		$renderer->configure_user($user, $config, $auth); + +		$container->set('text_formatter.renderer', $renderer); +		$container->set('text_formatter.s9e.renderer', $renderer); + +		// Create and register the text_formatter.s9e.utils service and its alias +		$utils = new \phpbb\textformatter\s9e\utils; +		$container->set('text_formatter.utils', $utils); +		$container->set('text_formatter.s9e.utils', $utils); + +		return $container; +	} + +	/** +	* Mocked replacement for \phpbb\user::format_date() +	* +	* @param  integer $gmepoch unix timestamp +	* @return string +	*/ +	static public function format_date($gmepoch) +	{ +		return gmdate('Y-m-d H:i:s', $gmepoch); +	}  } diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php index e8b230ecbe..e3f636679c 100644 --- a/tests/test_framework/phpbb_ui_test_case.php +++ b/tests/test_framework/phpbb_ui_test_case.php @@ -16,7 +16,7 @@ use Facebook\WebDriver\Exception\WebDriverCurlException;  use Facebook\WebDriver\Remote\RemoteWebDriver;  use Facebook\WebDriver\Remote\DesiredCapabilities; -require_once __DIR__ . '/../../phpBB/includes/functions_install.php'; +require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php';  class phpbb_ui_test_case extends phpbb_test_case  { @@ -32,7 +32,6 @@ class phpbb_ui_test_case extends phpbb_test_case  	static protected $root_url;  	static protected $already_installed = false;  	static protected $install_success = false; -  	protected $cache = null;  	protected $db = null;  	protected $extension_manager = null; @@ -191,90 +190,111 @@ class phpbb_ui_test_case extends phpbb_test_case  			}  		} +		$container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx); +		$container = $container_builder +			->with_environment('installer') +			->without_extensions() +			->without_cache() +			->with_custom_parameters([ +				'core.disable_super_globals' => false, +				'installer.create_config_file.options' => [ +					'debug' => true, +					'environment' => 'test', +				], +				'cache.driver.class' => 'phpbb\cache\driver\file' +			]) +			->without_compiled_container() +			->get_container(); + +		$container->register('installer.install_finish.notify_user')->setSynthetic(true); +		$container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task()); +		$container->compile(); + +		$language = $container->get('language'); +		$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting')); + +		$iohandler_factory = $container->get('installer.helper.iohandler_factory'); +		$iohandler_factory->set_environment('cli'); +		$iohandler = $iohandler_factory->get(); +  		$parseURL = parse_url(self::$config['phpbb_functional_url']); -		self::visit('install/index.php?mode=install&language=en'); -		self::assertContains('Welcome to Installation', self::find_element('id', 'main')->getText()); - -		// install/index.php?mode=install&sub=requirements -		self::submit(); -		self::assertContains('Installation compatibility', self::find_element('id', 'main')->getText()); - -		// install/index.php?mode=install&sub=database -		self::submit(); -		self::assertContains('Database configuration', self::find_element('id', 'main')->getText()); - -		self::find_element('id','dbms')->sendKeys(str_replace('phpbb\db\driver\\', '',  self::$config['dbms'])); -		self::find_element('id','dbhost')->sendKeys(self::$config['dbhost']); -		self::find_element('id','dbport')->sendKeys(self::$config['dbport']); -		self::find_element('id','dbname')->sendKeys(self::$config['dbname']); -		self::find_element('id','dbuser')->sendKeys(self::$config['dbuser']); -		self::find_element('id','dbpasswd')->sendKeys(self::$config['dbpasswd']); - -		// Need to clear default phpbb_ prefix -		self::find_element('id','table_prefix')->clear(); -		self::find_element('id','table_prefix')->sendKeys(self::$config['table_prefix']); - -		// install/index.php?mode=install&sub=database -		self::submit(); -		self::assertContains('Successful connection', self::find_element('id','main')->getText()); - -		// install/index.php?mode=install&sub=administrator -		self::submit(); -		self::assertContains('Administrator configuration', self::find_element('id','main')->getText()); - -		self::find_element('id','admin_name')->sendKeys('admin'); -		self::find_element('id','admin_pass1')->sendKeys('adminadmin'); -		self::find_element('id','admin_pass2')->sendKeys('adminadmin'); -		self::find_element('id','board_email')->sendKeys('nobody@example.com'); - -		// install/index.php?mode=install&sub=administrator -		self::submit(); -		self::assertContains('Tests passed', self::find_element('id','main')->getText()); - -		// install/index.php?mode=install&sub=config_file -		self::submit(); - -		// Installer has created a config.php file, we will overwrite it with a -		// config file of our own in order to get the DEBUG constants defined -		$config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true); -		$config_created = file_put_contents($config_file, $config_php_data) !== false; -		if (!$config_created) +		$output = new \Symfony\Component\Console\Output\NullOutput(); +		$style = new \Symfony\Component\Console\Style\SymfonyStyle( +			new \Symfony\Component\Console\Input\ArrayInput(array()), +			$output +		); +		$iohandler->set_style($style, $output); + +		$installer = $container->get('installer.installer.install'); +		$installer->set_iohandler($iohandler); + +		// Set data +		$iohandler->set_input('admin_name', 'admin'); +		$iohandler->set_input('admin_pass1', 'adminadmin'); +		$iohandler->set_input('admin_pass2', 'adminadmin'); +		$iohandler->set_input('board_email', 'nobody@example.com'); +		$iohandler->set_input('submit_admin', 'submit'); + +		$iohandler->set_input('default_lang', 'en'); +		$iohandler->set_input('board_name', 'yourdomain.com'); +		$iohandler->set_input('board_description', 'A short text to describe your forum'); +		$iohandler->set_input('submit_board', 'submit'); + +		$iohandler->set_input('dbms', str_replace('phpbb\db\driver\\', '',  self::$config['dbms'])); +		$iohandler->set_input('dbhost', self::$config['dbhost']); +		$iohandler->set_input('dbport', self::$config['dbport']); +		$iohandler->set_input('dbuser', self::$config['dbuser']); +		$iohandler->set_input('dbpasswd', self::$config['dbpasswd']); +		$iohandler->set_input('dbname', self::$config['dbname']); +		$iohandler->set_input('table_prefix', self::$config['table_prefix']); +		$iohandler->set_input('submit_database', 'submit'); + +		$iohandler->set_input('email_enable', true); +		$iohandler->set_input('smtp_delivery', '1'); +		$iohandler->set_input('smtp_host', 'nxdomain.phpbb.com'); +		$iohandler->set_input('smtp_auth', 'PLAIN'); +		$iohandler->set_input('smtp_user', 'nxuser'); +		$iohandler->set_input('smtp_pass', 'nxpass'); +		$iohandler->set_input('submit_email', 'submit'); + +		$iohandler->set_input('cookie_secure', '0'); +		$iohandler->set_input('server_protocol', '0'); +		$iohandler->set_input('force_server_vars', $parseURL['scheme'] . '://'); +		$iohandler->set_input('server_name', $parseURL['host']); +		$iohandler->set_input('server_port', isset($parseURL['port']) ? (int) $parseURL['port'] : 80); +		$iohandler->set_input('script_path', $parseURL['path']); +		$iohandler->set_input('submit_server', 'submit'); + +		$installer->run(); + +		copy($config_file, $config_file_test); + +		self::$install_success = true; + +		if (file_exists($phpbb_root_path . 'store/install_config.php'))  		{ -			self::markTestSkipped("Could not write $config_file file."); +			self::$install_success = false; +			@unlink($phpbb_root_path . 'store/install_config.php');  		} -		if (strpos(self::find_element('id','main')->getText(), 'The configuration file has been written') === false) +		if (file_exists($phpbb_root_path . 'cache/install_lock'))  		{ -			self::submit('id', 'dldone'); +			@unlink($phpbb_root_path . 'cache/install_lock');  		} -		self::assertContains('The configuration file has been written', self::find_element('id','main')->getText()); - -		// install/index.php?mode=install&sub=advanced -		self::submit(); -		self::assertContains('The settings on this page are only necessary to set if you know that you require something different from the default.', self::find_element('id','main')->getText()); - -		self::find_element('id','smtp_delivery')->sendKeys('1'); -		self::find_element('id','smtp_host')->sendKeys('nxdomain.phpbb.com'); -		self::find_element('id','smtp_user')->sendKeys('nxuser'); -		self::find_element('id','smtp_pass')->sendKeys('nxpass'); -		self::find_element('id','server_protocol')->sendKeys($parseURL['scheme'] . '://'); -		self::find_element('id','server_name')->sendKeys('localhost'); -		self::find_element('id','server_port')->sendKeys(isset($parseURL['port']) ? $parseURL['port'] : 80); -		self::find_element('id','script_path')->sendKeys($parseURL['path']); - -		// install/index.php?mode=install&sub=create_table -		self::submit(); -		self::assertContains('The database tables used by phpBB', self::find_element('id','main')->getText()); -		self::assertContains('have been created and populated with some initial data.', self::find_element('id','main')->getText()); - -		// install/index.php?mode=install&sub=final -		self::submit(); -		self::assertContains('You have successfully installed', self::find_element('id', 'main')->getText()); -		copy($config_file, $config_file_test); +		global $phpbb_container; +		$phpbb_container->reset(); -		self::$install_success = true; +		$blacklist = ['phpbb_class_loader_mock', 'phpbb_class_loader_ext', 'phpbb_class_loader']; + +		foreach (array_keys($GLOBALS) as $key) +		{ +			if (is_object($GLOBALS[$key]) && !in_array($key, $blacklist, true)) +			{ +				unset($GLOBALS[$key]); +			} +		}  	}  	public function install_ext($extension) diff --git a/tests/text_formatter/s9e/default_formatting_test.php b/tests/text_formatter/s9e/default_formatting_test.php new file mode 100644 index 0000000000..e25c3246b5 --- /dev/null +++ b/tests/text_formatter/s9e/default_formatting_test.php @@ -0,0 +1,313 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_textformatter_s9e_default_formatting_test extends phpbb_test_case +{ +	public function test_bbcode_code_lang_is_saved() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$parser    = $container->get('text_formatter.parser'); + +		$original = '[code]...[/code][code=php]...[/code]'; +		$expected = '<r><CODE><s>[code]</s>...<e>[/code]</e></CODE><CODE lang="php"><s>[code=php]</s>...<e>[/code]</e></CODE></r>'; + +		$this->assertXmlStringEqualsXmlString($expected, $parser->parse($original)); +	} + +	/** +	* @dataProvider get_default_formatting_tests +	*/ +	public function test_default_formatting($original, $expected, $setup = null) +	{ +		$fixture   = __DIR__ . '/fixtures/default_formatting.xml'; +		$container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); + +		$parser   = $container->get('text_formatter.parser'); +		$renderer = $container->get('text_formatter.renderer'); + +		if (isset($setup)) +		{ +			call_user_func($setup, $container); +		} + +		$parsed_text = $parser->parse($original); + +		$this->assertSame($expected, $renderer->render($parsed_text)); +	} + +	public function get_default_formatting_tests() +	{ +		return array( +			array( +				'[b]bold[/b]', +				'<span style="font-weight: bold">bold</span>' +			), +			array( +				'[u]underlined[/u]', +				'<span style="text-decoration: underline">underlined</span>' +			), +			array( +				'[i]italic[/i]', +				'<span style="font-style: italic">italic</span>' +			), +			array( +				'[color=#FF0000]colored[/color]', +				'<span style="color: #FF0000">colored</span>' +			), +			array( +				'[color=red]colored[/color]', +				'<span style="color: red">colored</span>' +			), +			array( +				'[size=75]smaller[/size]', +				'<span style="font-size: 75%; line-height: normal">smaller</span>' +			), +			array( +				'[quote]quoted[/quote]', +				'<blockquote class="uncited"><div>quoted</div></blockquote>' +			), +			array( +				'[quote="username"]quoted[/quote]', +				'<blockquote><div><cite>username wrote:</cite>quoted</div></blockquote>' +			), +			array( +				'[code]unparsed code[/code]', +				'<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>unparsed code</code></pre></div>' +			), +			array( +				'[list]no item[/list]', +				'<ul><li>no item</li></ul>' +			), +			array( +				'[*]unparsed', +				'[*]unparsed' +			), +			array( +				'[list][*]item[/list]', +				'<ul><li>item</li></ul>' +			), +			array( +				'[list][*]item[/*][/list]', +				'<ul><li>item</li></ul>' +			), +			array( +				'[list=1][*]item[/list]', +				'<ol style="list-style-type: decimal"><li>item</li></ol>' +			), +			array( +				'[list=a][*]item[/list]', +				'<ol style="list-style-type: lower-alpha"><li>item</li></ol>' +			), +			array( +				'[list=i][*]item[/list]', +				'<ol style="list-style-type: lower-roman"><li>item</li></ol>' +			), +			array( +				'[list=I][*]item[/list]', +				'<ol style="list-style-type: upper-roman"><li>item</li></ol>' +			), +			array( +				'[list=disc][*]item[/list]', +				'<ul style="list-style-type: disc"><li>item</li></ul>' +			), +			array( +				'[list=circle][*]item[/list]', +				'<ul style="list-style-type: circle"><li>item</li></ul>' +			), +			array( +				'[list=square][*]item[/list]', +				'<ul style="list-style-type: square"><li>item</li></ul>' +			), +			array( +				'[img]https://area51.phpbb.com/images/area51.png[/img]', +				'<img src="https://area51.phpbb.com/images/area51.png" class="postimage" alt="Image">' +			), +			array( +				'[url]https://area51.phpbb.com/[/url]', +				'<a href="https://area51.phpbb.com/" class="postlink">https://area51.phpbb.com/</a>' +			), +			array( +				'[url=https://area51.phpbb.com/]Area51[/url]', +				'<a href="https://area51.phpbb.com/" class="postlink">Area51</a>' +			), +			array( +				'[email]bbcode-test@phpbb.com[/email]', +				'<a href="mailto:bbcode-test@phpbb.com">bbcode-test@phpbb.com</a>' +			), +			array( +				'[email=bbcode-test@phpbb.com]Email[/email]', +				'<a href="mailto:bbcode-test@phpbb.com">Email</a>' +			), +			array( +				'[attachment=0]filename[/attachment]', +				'<div class="inline-attachment"><!-- ia0 -->filename<!-- ia0 --></div>' +			), +			array( +				// PHPBB3-1401 - correct: parsed +				'[quote="[test]test"]test [ test[/quote]', +				'<blockquote><div><cite>[test]test wrote:</cite>test [ test</div></blockquote>' +			), +			array( +				// PHPBB3-6117 - correct: parsed +				'[quote]test[/quote] test ] and [ test [quote]test[/quote]', +				'<blockquote class="uncited"><div>test</div></blockquote> test ] and [ test <blockquote class="uncited"><div>test</div></blockquote>' +			), +			array( +				// PHPBB3-6200 - correct: parsed +				'[quote="["]test[/quote]', +				'<blockquote><div><cite>[ wrote:</cite>test</div></blockquote>' +			), +			array( +				// PHPBB3-9364 - quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted +				'[quote]test[/[/b]quote] test [/quote][/quote] test', +				'<blockquote class="uncited"><div>test[/[/b]quote] test </div></blockquote>[/quote] test' +			), +			array( +				// PHPBB3-8096 - first quote tag parsed, second quote tag unparsed +				'[quote="a"]a[/quote][quote="a]a[/quote]', +				'<blockquote><div><cite>a wrote:</cite>a</div></blockquote>[quote="a]a[/quote]' +			), +			array( +				// Allow textual bbcodes in textual bbcodes +				'[b]bold [i]bold + italic[/i][/b]', +				'<span style="font-weight: bold">bold <span style="font-style: italic">bold + italic</span></span>' +			), +			array( +				// Allow textual bbcodes in url with description +				'[url=https://area51.phpbb.com/]Area51 [i]italic[/i][/url]', +				'<a href="https://area51.phpbb.com/" class="postlink">Area51 <span style="font-style: italic">italic</span></a>' +			), +			array( +				// Allow url with description in textual bbcodes +				'[i]italic [url=https://area51.phpbb.com/]Area51[/url][/i]', +				'<span style="font-style: italic">italic <a href="https://area51.phpbb.com/" class="postlink">Area51</a></span>' +			), +			array( +				// Do not parse textual bbcodes in code +				'[code]unparsed code [b]bold [i]bold + italic[/i][/b][/code]', +				'<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>unparsed code [b]bold [i]bold + italic[/i][/b]</code></pre></div>' +			), +			array( +				// Do not parse quote bbcodes in code +				'[code]unparsed code [quote="username"]quoted[/quote][/code]', +				'<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>unparsed code [quote="username"]quoted[/quote]</code></pre></div>' +			), +			array( +				// Textual bbcode nesting into textual bbcode +				'[b]bold [i]bold + italic[/b] italic[/i]', +				'<span style="font-weight: bold">bold <span style="font-style: italic">bold + italic</span></span><span style="font-style: italic"> italic</span>' +			), +			array( +				"[code]\tline1\n  line2[/code]", +				'<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>' . "\tline1\n  line2</code></pre></div>" +			), +			array( +				"[code]\n\tline1\n  line2[/code]", +				'<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>' . "\tline1\n  line2</code></pre></div>" +			), +			array( +				'... http://example.org ...', +				'... <a href="http://example.org" class="postlink">http://example.org</a> ...' +			), +			array( +				'... www.example.org ...', +				'... <a href="http://www.example.org" class="postlink">www.example.org</a> ...' +			), +			array( +				// From make_clickable_test.php +				'www.phpbb.com/community/?', +				'<a href="http://www.phpbb.com/community/" class="postlink">www.phpbb.com/community/</a>?' +			), +			array( +				// From make_clickable_test.php +				'http://www.phpbb.com/community/path/to/long/url/file.ext#section', +				'<a href="http://www.phpbb.com/community/path/to/long/url/file.ext#section" class="postlink">http://www.phpbb.com/community/path/to/ ... xt#section</a>' +			), +			array( +				'http://localhost/ http://localhost/phpbb/ http://localhost/phpbb/viewforum.php?f=1', +				'<a href="http://localhost/" class="postlink">http://localhost/</a> <a href="http://localhost/phpbb/" class="postlink">http://localhost/phpbb/</a> <a href="http://localhost/phpbb/viewforum.php?f=1" class="postlink">viewforum.php?f=1</a>' +			), +			array( +				'http://localhost/phpbb/viewforum.php?f=1#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', +				'<a href="http://localhost/phpbb/viewforum.php?f=1#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" class="postlink">viewforum.php?f=1#xxxxxxxxxxxxxxxxxxxxx ... xxxxxxxxxx</a>' +			), +			array( +				'[url]http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0[/url]', +				'<a href="http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0" class="postlink">http://example.org/0xxxxxxxxxxxxxxxxxxx ... xxxxxxxxx0</a>' +			), +			array( +				'[URL]http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0[/url]', +				'<a href="http://example.org/0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0" class="postlink">http://example.org/0xxxxxxxxxxxxxxxxxxx ... xxxxxxxxx0</a>' +			), +			array( +				'[url=http://example.org/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[/url]', +				'<a href="http://example.org/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" class="postlink">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</a>' +			), +			array( +				'[quote="[url=http://example.org]xxx[/url]"]...[/quote]', +				'<blockquote><div><cite><a href="http://example.org" class="postlink">xxx</a> wrote:</cite>...</div></blockquote>' +			), +			array( +				'[quote="[url]http://example.org[/url]"]...[/quote]', +				'<blockquote><div><cite><a href="http://example.org" class="postlink">http://example.org</a> wrote:</cite>...</div></blockquote>' +			), +			array( +				'[quote=http://example.org]...[/quote]', +				'<blockquote><div><cite><a href="http://example.org" class="postlink">http://example.org</a> wrote:</cite>...</div></blockquote>' +			), +			array( +				"[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]\n\nFollowed by a reply", +				"<blockquote class=\"uncited\"><div>\nThis is a long quote that is definitely going to exceed 80 characters\n</div></blockquote>\n\nFollowed by a reply" +			), +			array( +				'[quote=Username post_id=123]...[/quote]', +				'<blockquote><div><cite>Username wrote: <a href="phpBB/viewtopic.php?p=123#p123" data-post-id="123" onclick="if(document.getElementById(hash.substr(1)))href=hash">↑</a></cite>...</div></blockquote>' +			), +			array( +				// Users are not allowed to submit their own URL for the post +				'[quote="Username" post_url="http://fake.example.org"]...[/quote]', +				'<blockquote><div><cite>Username wrote:</cite>...</div></blockquote>' +			), +			array( +				'[quote=Username time=58705871]...[/quote]', +				'<blockquote><div><cite>Username wrote:<div class="responsive-hide">1971-11-11 11:11:11</div></cite>...</div></blockquote>' +			), +			array( +				'[quote=Username user_id=123]...[/quote]', +				'<blockquote><div><cite><a href="phpBB/memberlist.php?mode=viewprofile&u=123">Username</a> wrote:</cite>...</div></blockquote>' +			), +			array( +				// Users are not allowed to submit their own URL for the profile +				'[quote=Username profile_url=http://fake.example.org]...[/quote]', +				'<blockquote><div><cite>Username wrote:</cite>...</div></blockquote>' +			), +			array( +				// From phpbb_textformatter_s9e_utils_test::test_generate_quote() +				'[quote=\'[quote="foo"]\']...[/quote]', +				'<blockquote><div><cite>[quote="foo"] wrote:</cite>...</div></blockquote>' +			), +			array( +				"Emoji: \xF0\x9F\x98\x80", +				'Emoji: <img alt="' . "\xF0\x9F\x98\x80" . '" class="smilies" draggable="false" width="18" height="18" src="//cdn.jsdelivr.net/emojione/assets/svg/1f600.svg">' +			), +			array( +				"Emoji: \xF0\x9F\x98\x80", +				"Emoji: \xF0\x9F\x98\x80", +				function ($container) +				{ +					$container->get('text_formatter.renderer')->set_viewsmilies(false); +				} +			), +		); +	} +} diff --git a/tests/text_formatter/s9e/factory_test.php b/tests/text_formatter/s9e/factory_test.php new file mode 100644 index 0000000000..3d3ea8b794 --- /dev/null +++ b/tests/text_formatter/s9e/factory_test.php @@ -0,0 +1,263 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; + +class phpbb_textformatter_s9e_factory_test extends phpbb_database_test_case +{ +	public function setUp() +	{ +		$this->cache = new phpbb_mock_cache; +		$this->dispatcher = new phpbb_mock_event_dispatcher; +		parent::setUp(); +	} + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/factory.xml'); +	} + +	public function get_cache_dir() +	{ +		return __DIR__ . '/../../tmp/'; +	} + +	public function get_factory() +	{ +		global $config, $phpbb_root_path, $request, $user; +		$this->cache = new phpbb_mock_cache; +		$dal = new \phpbb\textformatter\data_access( +			$this->new_dbal(), +			'phpbb_bbcodes', +			'phpbb_smilies', +			'phpbb_styles', +			'phpbb_words', +			$phpbb_root_path . 'styles/' +		); +		$factory = new \phpbb\textformatter\s9e\factory( +			$dal, +			$this->cache, +			$this->dispatcher, +			new \phpbb\config\config(array('allowed_schemes_links' => 'http,https,ftp')), +			new \phpbb\textformatter\s9e\link_helper, +			$this->get_cache_dir(), +			'_foo_parser', +			'_foo_renderer' +		); + +		// Global objects required by generate_board_url() +		$config = new \phpbb\config\config(array( +			'script_path'           => '/phpbb', +			'server_name'           => 'localhost', +			'server_port'           => 80, +			'server_protocol'       => 'http://', +		)); +		$request = new phpbb_mock_request; +		$user = new phpbb_mock_user; + +		return $factory; +	} + +	public function test_get_configurator() +	{ +		$configurator = $this->get_factory()->get_configurator(); + +		$this->assertInstanceOf('s9e\\TextFormatter\\Configurator', $configurator); + +		$this->assertTrue(isset($configurator->plugins['Autoemail'])); +		$this->assertTrue(isset($configurator->plugins['Autolink'])); + +		$this->assertTrue(isset($configurator->BBCodes['B'])); +		$this->assertTrue(isset($configurator->BBCodes['CODE'])); +		$this->assertTrue(isset($configurator->BBCodes['COLOR'])); +		$this->assertTrue(isset($configurator->BBCodes['EMAIL'])); +		$this->assertTrue(isset($configurator->BBCodes['FLASH'])); +		$this->assertTrue(isset($configurator->BBCodes['I'])); +		$this->assertTrue(isset($configurator->BBCodes['IMG'])); +		$this->assertTrue(isset($configurator->BBCodes['LIST'])); +		$this->assertTrue(isset($configurator->BBCodes['*'])); +		$this->assertTrue(isset($configurator->BBCodes['QUOTE'])); +		$this->assertTrue(isset($configurator->BBCodes['SIZE'])); +		$this->assertTrue(isset($configurator->BBCodes['U'])); +		$this->assertTrue(isset($configurator->BBCodes['URL'])); + +		// This custom BBCode should be set +		$this->assertTrue(isset($configurator->BBCodes['CUSTOM'])); + +		$this->assertTrue(isset($configurator->Emoticons[':D'])); +	} + +	public function test_regenerate() +	{ +		extract($this->get_factory()->regenerate()); + +		$this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser); +		$this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer); + +		$renderer_data = $this->cache->get('_foo_renderer'); +		$this->assertEquals($parser, $this->cache->get('_foo_parser'), 'The parser was not cached'); +		$this->assertEquals(get_class($renderer), $renderer_data['class']); +		$this->assertInstanceOf('s9e\\TextFormatter\\Plugins\\Censor\\Helper', $renderer_data['censor']); + +		$file = $this->get_cache_dir() . get_class($renderer) . '.php'; +		$this->assertFileExists($file); +		unlink($file); +	} + +	public function test_tidy() +	{ +		$factory = $this->get_factory(); + +		// Create a fake "old" cache file +		$old_file = $this->get_cache_dir() . 's9e_foo.php'; +		touch($old_file); + +		// Create a current renderer +		extract($factory->regenerate()); +		$new_file = $this->get_cache_dir() . get_class($renderer) . '.php'; + +		// Tidy the cache +		$factory->tidy(); + +		$this->assertFileExists($new_file, 'The current renderer has been deleted'); +		$this->assertFileNotExists($old_file, 'The old renderer has not been deleted'); + +		unlink($new_file); +	} + +	public function test_local_url() +	{ +		global $config, $user, $request; +		$config = new \phpbb\config\config(array( +			'force_server_vars' => true, +			'server_protocol' => 'http://', +			'server_name' => 'path', +			'server_port' => 80, +			'script_path' => '/to', +			'cookie_secure' => false +		)); +		$user = new phpbb_mock_user; +		$request = new phpbb_mock_request; + +		$fixture = __DIR__ . '/fixtures/local_url.xml'; +		$renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer'); + +		$this->assertSame( +			'<a href="http://path/to/foo">http://path/to/foo</a>', +			$renderer->render('<r><LOCAL content="foo"><s>[local]</s>foo<e>[/local]</e></LOCAL></r>') +		); +	} + +	public function test_smilies_special_chars() +	{ +		// Use a smiley that contains every special chars in every field +		$fixture = __DIR__ . '/fixtures/smilies_special_chars.xml'; +		$renderer = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.renderer'); + +		$this->assertSame( +			'<img class="smilies" src="phpBB/images/smilies/%22%27%3C&%3E.png" width="15" height="17" alt=""\'<&>" title=""\'<&>">', +			$renderer->render('<r><E>"\'<&></E></r>') +		); +	} + +	public function test_duplicate_smilies() +	{ +		$fixture = __DIR__ . '/fixtures/smilies_duplicate.xml'; +		$parser = $this->get_test_case_helpers()->set_s9e_services(null, $fixture)->get('text_formatter.parser'); + +		$this->assertSame( +			'<r><E>:)</E></r>', +			$parser->parse(':)') +		); +	} + +	/** +	* @testdox {INTTEXT} is supported in custom BBCodes +	*/ +	public function test_inttext_token() +	{ +		$fixture = __DIR__ . '/fixtures/inttext_token.xml'; +		$container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); +		$parser = $container->get('text_formatter.parser'); +		$renderer = $container->get('text_formatter.renderer'); + +		$original = '[spoiler=ɎɆS]text[/spoiler]'; +		$expected = '<div class="spoiler"><div class="title">ɎɆS</div><div class="content">text</div></div>'; +		$this->assertSame($expected, $renderer->render($parser->parse($original))); + +		$original = '[spoiler=N:O:P:E]text[/spoiler]'; +		$expected = $original; +		$this->assertSame($expected, $renderer->render($parser->parse($original))); +	} + +	/** +	* @testdox Preserves comments in custom BBCodes +	*/ +	public function test_preserve_comments() +	{ +		$fixture = __DIR__ . '/fixtures/preserve_comments.xml'; +		$container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); +		$parser = $container->get('text_formatter.parser'); +		$renderer = $container->get('text_formatter.renderer'); + +		$original = '[X]'; +		$expected = '<!-- comment -->'; +		$this->assertSame($expected, $renderer->render($parser->parse($original))); +	} + +	/** +	* @testdox Accepts unsafe custom BBCodes +	*/ +	public function test_unsafe_bbcode() +	{ +		$fixture = __DIR__ . '/fixtures/unsafe_bbcode.xml'; +		$container = $this->get_test_case_helpers()->set_s9e_services(null, $fixture); +		$parser = $container->get('text_formatter.parser'); +		$renderer = $container->get('text_formatter.renderer'); + +		$original = '[xss=javascript:alert(1)]text[/xss]'; +		$expected = '<a href="javascript:alert(1)">text</a>'; +		$this->assertSame($expected, $renderer->render($parser->parse($original))); +	} + +	/** +	* @testdox get_configurator() triggers events before and after configuration +	*/ +	public function test_configure_events() +	{ +		$this->dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); +		$this->dispatcher +			->expects($this->at(0)) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_configure_before', +				$this->callback(array($this, 'configure_event_callback')) +			) +			->will($this->returnArgument(1)); +		$this->dispatcher +			->expects($this->at(1)) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_configure_after', +				$this->callback(array($this, 'configure_event_callback')) +			) +			->will($this->returnArgument(1)); + +		$this->get_factory()->get_configurator(); +	} + +	public function configure_event_callback($vars) +	{ +		return isset($vars['configurator']) && $vars['configurator'] instanceof \s9e\TextFormatter\Configurator; +	} +} diff --git a/tests/text_formatter/s9e/fixtures/default_formatting.xml b/tests/text_formatter/s9e/fixtures/default_formatting.xml new file mode 100644 index 0000000000..2b7236fb30 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/default_formatting.xml @@ -0,0 +1,466 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>1</value> +			<value>:D</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>1</value> +			<value>1</value> +		</row> +		<row> +			<value>2</value> +			<value>:-D</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>2</value> +			<value>1</value> +		</row> +		<row> +			<value>3</value> +			<value>:grin:</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>3</value> +			<value>1</value> +		</row> +		<row> +			<value>4</value> +			<value>:)</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>4</value> +			<value>1</value> +		</row> +		<row> +			<value>5</value> +			<value>:-)</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>5</value> +			<value>1</value> +		</row> +		<row> +			<value>6</value> +			<value>:smile:</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>6</value> +			<value>1</value> +		</row> +		<row> +			<value>7</value> +			<value>;)</value> +			<value>Wink</value> +			<value>icon_e_wink.gif</value> +			<value>15</value> +			<value>17</value> +			<value>7</value> +			<value>1</value> +		</row> +		<row> +			<value>8</value> +			<value>;-)</value> +			<value>Wink</value> +			<value>icon_e_wink.gif</value> +			<value>15</value> +			<value>17</value> +			<value>8</value> +			<value>1</value> +		</row> +		<row> +			<value>9</value> +			<value>:wink:</value> +			<value>Wink</value> +			<value>icon_e_wink.gif</value> +			<value>15</value> +			<value>17</value> +			<value>9</value> +			<value>1</value> +		</row> +		<row> +			<value>10</value> +			<value>:(</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>10</value> +			<value>1</value> +		</row> +		<row> +			<value>11</value> +			<value>:-(</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>11</value> +			<value>1</value> +		</row> +		<row> +			<value>12</value> +			<value>:sad:</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>12</value> +			<value>1</value> +		</row> +		<row> +			<value>13</value> +			<value>:o</value> +			<value>Surprised</value> +			<value>icon_e_surprised.gif</value> +			<value>15</value> +			<value>17</value> +			<value>13</value> +			<value>1</value> +		</row> +		<row> +			<value>14</value> +			<value>:-o</value> +			<value>Surprised</value> +			<value>icon_e_surprised.gif</value> +			<value>15</value> +			<value>17</value> +			<value>14</value> +			<value>1</value> +		</row> +		<row> +			<value>15</value> +			<value>:eek:</value> +			<value>Surprised</value> +			<value>icon_e_surprised.gif</value> +			<value>15</value> +			<value>17</value> +			<value>15</value> +			<value>1</value> +		</row> +		<row> +			<value>16</value> +			<value>:shock:</value> +			<value>Shocked</value> +			<value>icon_eek.gif</value> +			<value>15</value> +			<value>17</value> +			<value>16</value> +			<value>1</value> +		</row> +		<row> +			<value>17</value> +			<value>:?</value> +			<value>Confused</value> +			<value>icon_e_confused.gif</value> +			<value>15</value> +			<value>17</value> +			<value>17</value> +			<value>1</value> +		</row> +		<row> +			<value>18</value> +			<value>:-?</value> +			<value>Confused</value> +			<value>icon_e_confused.gif</value> +			<value>15</value> +			<value>17</value> +			<value>18</value> +			<value>1</value> +		</row> +		<row> +			<value>19</value> +			<value>:???:</value> +			<value>Confused</value> +			<value>icon_e_confused.gif</value> +			<value>15</value> +			<value>17</value> +			<value>19</value> +			<value>1</value> +		</row> +		<row> +			<value>20</value> +			<value>8-)</value> +			<value>Cool</value> +			<value>icon_cool.gif</value> +			<value>15</value> +			<value>17</value> +			<value>20</value> +			<value>1</value> +		</row> +		<row> +			<value>21</value> +			<value>:cool:</value> +			<value>Cool</value> +			<value>icon_cool.gif</value> +			<value>15</value> +			<value>17</value> +			<value>21</value> +			<value>1</value> +		</row> +		<row> +			<value>22</value> +			<value>:lol:</value> +			<value>Laughing</value> +			<value>icon_lol.gif</value> +			<value>15</value> +			<value>17</value> +			<value>22</value> +			<value>1</value> +		</row> +		<row> +			<value>23</value> +			<value>:x</value> +			<value>Mad</value> +			<value>icon_mad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>23</value> +			<value>1</value> +		</row> +		<row> +			<value>24</value> +			<value>:-x</value> +			<value>Mad</value> +			<value>icon_mad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>24</value> +			<value>1</value> +		</row> +		<row> +			<value>25</value> +			<value>:mad:</value> +			<value>Mad</value> +			<value>icon_mad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>25</value> +			<value>1</value> +		</row> +		<row> +			<value>26</value> +			<value>:P</value> +			<value>Razz</value> +			<value>icon_razz.gif</value> +			<value>15</value> +			<value>17</value> +			<value>26</value> +			<value>1</value> +		</row> +		<row> +			<value>27</value> +			<value>:-P</value> +			<value>Razz</value> +			<value>icon_razz.gif</value> +			<value>15</value> +			<value>17</value> +			<value>27</value> +			<value>1</value> +		</row> +		<row> +			<value>28</value> +			<value>:razz:</value> +			<value>Razz</value> +			<value>icon_razz.gif</value> +			<value>15</value> +			<value>17</value> +			<value>28</value> +			<value>1</value> +		</row> +		<row> +			<value>29</value> +			<value>:oops:</value> +			<value>Embarrassed</value> +			<value>icon_redface.gif</value> +			<value>15</value> +			<value>17</value> +			<value>29</value> +			<value>1</value> +		</row> +		<row> +			<value>30</value> +			<value>:cry:</value> +			<value>Crying or Very Sad</value> +			<value>icon_cry.gif</value> +			<value>15</value> +			<value>17</value> +			<value>30</value> +			<value>1</value> +		</row> +		<row> +			<value>31</value> +			<value>:evil:</value> +			<value>Evil or Very Mad</value> +			<value>icon_evil.gif</value> +			<value>15</value> +			<value>17</value> +			<value>31</value> +			<value>1</value> +		</row> +		<row> +			<value>32</value> +			<value>:twisted:</value> +			<value>Twisted Evil</value> +			<value>icon_twisted.gif</value> +			<value>15</value> +			<value>17</value> +			<value>32</value> +			<value>1</value> +		</row> +		<row> +			<value>33</value> +			<value>:roll:</value> +			<value>Rolling Eyes</value> +			<value>icon_rolleyes.gif</value> +			<value>15</value> +			<value>17</value> +			<value>33</value> +			<value>1</value> +		</row> +		<row> +			<value>34</value> +			<value>:!:</value> +			<value>Exclamation</value> +			<value>icon_exclaim.gif</value> +			<value>15</value> +			<value>17</value> +			<value>34</value> +			<value>1</value> +		</row> +		<row> +			<value>35</value> +			<value>:?:</value> +			<value>Question</value> +			<value>icon_question.gif</value> +			<value>15</value> +			<value>17</value> +			<value>35</value> +			<value>1</value> +		</row> +		<row> +			<value>36</value> +			<value>:idea:</value> +			<value>Idea</value> +			<value>icon_idea.gif</value> +			<value>15</value> +			<value>17</value> +			<value>36</value> +			<value>1</value> +		</row> +		<row> +			<value>37</value> +			<value>:arrow:</value> +			<value>Arrow</value> +			<value>icon_arrow.gif</value> +			<value>15</value> +			<value>17</value> +			<value>37</value> +			<value>1</value> +		</row> +		<row> +			<value>38</value> +			<value>:|</value> +			<value>Neutral</value> +			<value>icon_neutral.gif</value> +			<value>15</value> +			<value>17</value> +			<value>38</value> +			<value>1</value> +		</row> +		<row> +			<value>39</value> +			<value>:-|</value> +			<value>Neutral</value> +			<value>icon_neutral.gif</value> +			<value>15</value> +			<value>17</value> +			<value>39</value> +			<value>1</value> +		</row> +		<row> +			<value>40</value> +			<value>:mrgreen:</value> +			<value>Mr. Green</value> +			<value>icon_mrgreen.gif</value> +			<value>15</value> +			<value>17</value> +			<value>40</value> +			<value>1</value> +		</row> +		<row> +			<value>41</value> +			<value>:geek:</value> +			<value>Geek</value> +			<value>icon_e_geek.gif</value> +			<value>17</value> +			<value>17</value> +			<value>41</value> +			<value>1</value> +		</row> +		<row> +			<value>42</value> +			<value>:ugeek:</value> +			<value>Uber Geek</value> +			<value>icon_e_ugeek.gif</value> +			<value>17</value> +			<value>18</value> +			<value>42</value> +			<value>1</value> +		</row> +	</table> + +	<table name="phpbb_styles"> +		<column>style_id</column> +		<column>style_name</column> +		<column>style_copyright</column> +		<column>style_active</column> +		<column>style_path</column> +		<column>bbcode_bitfield</column> +		<column>style_parent_id</column> +		<column>style_parent_tree</column> +		<row> +			<value>1</value> +			<value>prosilver</value> +			<value>&copy; phpBB Group</value> +			<value>1</value> +			<value>prosilver</value> +			<value>kNg=</value> +			<value>0</value> +			<value></value> +		</row> +	</table> + +	<table name="phpbb_words"> +		<column>word_id</column> +		<column>word</column> +		<column>replacement</column> + +		<row> +			<value>1</value> +			<value>apple</value> +			<value>banana</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/default_lang.xml b/tests/text_formatter/s9e/fixtures/default_lang.xml new file mode 100644 index 0000000000..2cfde4aab2 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/default_lang.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> + +		<row> +			<value>13</value> +			<value>foo</value> +			<value></value> +			<value>1</value> +			<value>[foo]{TEXT}[/foo]</value> +			<value>{L_FOO_BAR}</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/factory.xml b/tests/text_formatter/s9e/fixtures/factory.xml new file mode 100644 index 0000000000..9ae52e9747 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/factory.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>custom</value> +			<value></value> +			<value>1</value> +			<value>[custom]{TEXT}[/custom]</value> +			<value><span style="color:red">{TEXT}</span></value> +			<value>!\[custom\](.*?)\[/custom\]!ies</value> +			<value>'[custom:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/custom:$uid]'</value> +			<value>!\[custom:$uid\](.*?)\[/custom:$uid\]!s</value> +			<value><span style="color:red">${1}</span></value> +		</row> +		<row> +			<value>14</value> +			<value>unsafe</value> +			<value></value> +			<value>1</value> +			<value>[unsafe]{TEXT}[/unsafe]</value> +			<value><script>{TEXT}</script></value> +			<value>!\[unsafe\](.*?)\[/unsafe\]!ies</value> +			<value>'[unsafe:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/unsafe:$uid]'</value> +			<value>!\[unsafe:$uid\](.*?)\[/unsafe:$uid\]!s</value> +			<value><script>${1}</script></value> +		</row> +	</table> + +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>1</value> +			<value>:D</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>2</value> +			<value>1</value> +		</row> +		<row> +			<value>4</value> +			<value>:)</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>4</value> +			<value>1</value> +		</row> +		<row> +			<value>10</value> +			<value>:(</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>10</value> +			<value>1</value> +		</row> +	</table> + +	<table name="phpbb_styles"> +		<column>style_id</column> +		<column>style_name</column> +		<column>style_copyright</column> +		<column>style_active</column> +		<column>style_path</column> +		<column>bbcode_bitfield</column> +		<column>style_parent_id</column> +		<column>style_parent_tree</column> + +		<row> +			<value>1</value> +			<value>prosilver</value> +			<value>&copy; phpBB Group</value> +			<value>1</value> +			<value>prosilver</value> +			<value>kNg=</value> +			<value>0</value> +			<value></value> +		</row> +	</table> + +	<table name="phpbb_words"> +		<column>word_id</column> +		<column>word</column> +		<column>replacement</column> + +		<row> +			<value>1</value> +			<value>apple</value> +			<value>banana</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/inttext_token.xml b/tests/text_formatter/s9e/fixtures/inttext_token.xml new file mode 100644 index 0000000000..30b971f315 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/inttext_token.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>spoiler=</value> +			<value></value> +			<value>1</value> +			<value>[spoiler={INTTEXT}]{TEXT}[/spoiler]</value> +			<value><![CDATA[<div class="spoiler"><div class="title">{INTTEXT}</div><div class="content">{TEXT}</div></div>]]></value> +			<value><![CDATA[!\[spoiler\=([\p{L}\p{N}\-+,_. ]+)\](.*?)\[/spoiler\]!iues]]></value> +			<value><![CDATA['[spoiler=${1}:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/spoiler:$uid]']]></value> +			<value><![CDATA[!\[spoiler\=([\p{L}\p{N}\-+,_. ]+):$uid\](.*?)\[/spoiler:$uid\]!su]]></value><value><![CDATA[<div class="spoiler"><div class="title">${1}</div><div class="content">${2}</div></div>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/local_url.xml b/tests/text_formatter/s9e/fixtures/local_url.xml new file mode 100644 index 0000000000..9db2bf4710 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/local_url.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>local</value> +			<value></value> +			<value>1</value> +			<value>[local]{LOCAL_URL}[/local]</value> +			<value><![CDATA[<a href="{LOCAL_URL}">{LOCAL_URL}</a>]]></value> +			<value><*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?)\[/local\]!ie]]></value> +			<value><![CDATA['[local:$uid]'.$this->bbcode_specialchars('${1}').'[/local:$uid]']]></value> +			<value><((?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~\!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:#(?:[a-z0-9\-._~\!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?)(?-i)\[/local:$uid\]!s]]></value> +			<value><![CDATA[<a href="http://path/to/phpBB/${1}">http://path/to/phpBB/${1}</a>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/preserve_comments.xml b/tests/text_formatter/s9e/fixtures/preserve_comments.xml new file mode 100644 index 0000000000..f81d366aad --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/preserve_comments.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>X</value> +			<value></value> +			<value>1</value> +			<value>[X][/X]</value> +			<value><![CDATA[<!-- comment -->]]></value> +			<value><![CDATA[!\[x\]\[/x\]!i]]></value> +			<value><![CDATA[[x:$uid][/x:$uid]]]></value> +			<value><![CDATA[[x:$uid][/x:$uid]]]></value> +			<value></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/smilies_duplicate.xml b/tests/text_formatter/s9e/fixtures/smilies_duplicate.xml new file mode 100644 index 0000000000..9645f3e516 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/smilies_duplicate.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>1</value> +			<value>:)</value> +			<value>:)</value> +			<value>foo.png</value> +			<value>15</value> +			<value>17</value> +			<value>2</value> +			<value>1</value> +		</row> +		<row> +			<value>2</value> +			<value>:)</value> +			<value>:)</value> +			<value>bar.png</value> +			<value>15</value> +			<value>17</value> +			<value>2</value> +			<value>2</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml new file mode 100644 index 0000000000..d3a7cfa4f7 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/smilies_special_chars.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>1</value> +			<value>"'<&></value> +			<value>"'<&></value> +			<value>"'<&>.png</value> +			<value>15</value> +			<value>17</value> +			<value>2</value> +			<value>1</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/style_inheritance.xml b/tests/text_formatter/s9e/fixtures/style_inheritance.xml new file mode 100644 index 0000000000..a692d0ef2d --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/style_inheritance.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_styles"> +		<column>style_id</column> +		<column>style_name</column> +		<column>style_copyright</column> +		<column>style_active</column> +		<column>style_path</column> +		<column>bbcode_bitfield</column> +		<column>style_parent_id</column> +		<column>style_parent_tree</column> + +		<row> +			<value>1</value> +			<value>foo</value> +			<value></value> +			<value>1</value> +			<value>foo</value> +			<!-- Bitfield for "b" only --> +			<value>QA==</value> +			<value>0</value> +			<value></value> +		</row> +		<row> +			<value>2</value> +			<value>fooplus</value> +			<value></value> +			<value>1</value> +			<value>fooplus</value> +			<value>QA==</value> +			<value>1</value> +			<value></value> +		</row> +		<row> +			<value>3</value> +			<value>fooplusplus</value> +			<value></value> +			<value>1</value> +			<value>fooplusplus</value> +			<value>QA==</value> +			<value>2</value> +			<value></value> +		</row> +		<row> +			<value>4</value> +			<value>bar</value> +			<value></value> +			<value>1</value> +			<value>bar</value> +			<!-- Bitfield for "b" only --> +			<value>QA==</value> +			<value>0</value> +			<value></value> +		</row> +		<row> +			<value>5</value> +			<value>barplus</value> +			<value></value> +			<value>1</value> +			<value>barplus</value> +			<value>QA==</value> +			<value>4</value> +			<value></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/styles.xml b/tests/text_formatter/s9e/fixtures/styles.xml new file mode 100644 index 0000000000..8004412aea --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_styles"> +		<column>style_id</column> +		<column>style_name</column> +		<column>style_copyright</column> +		<column>style_active</column> +		<column>style_path</column> +		<column>bbcode_bitfield</column> +		<column>style_parent_id</column> +		<column>style_parent_tree</column> + +		<row> +			<value>1</value> +			<value>foo</value> +			<value></value> +			<value>1</value> +			<value>foo</value> +			<!-- Bitfield for "b" only --> +			<value>QA==</value> +			<value>0</value> +			<value></value> +		</row> +		<row> +			<value>2</value> +			<value>bar</value> +			<value></value> +			<value>1</value> +			<value>bar</value> +			<!-- Bitfield for "b" only --> +			<value>QA==</value> +			<value>0</value> +			<value></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html new file mode 100644 index 0000000000..76a35542be --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/bar/template/bbcode.html @@ -0,0 +1,40 @@ +<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open --> +<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default --> +<!-- BEGIN ulist_close --></ul><!-- END ulist_close --> + +<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open --> +<!-- BEGIN olist_close --></ol><!-- END olist_close --> + +<!-- BEGIN listitem --><li><!-- END listitem --> +<!-- BEGIN listitem_close --></li><!-- END listitem_close --> + +<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open --> +<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open --> +<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close --> + +<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open --> +<!-- BEGIN code_close --></code></div><!-- END code_close --> + +<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open --> +<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close --> + +<!-- BEGIN b_open --><b><!-- END b_open --> +<!-- BEGIN b_close --></b><!-- END b_close --> + +<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open --> +<!-- BEGIN u_close --></span><!-- END u_close --> + +<!-- BEGIN i_open --><em><!-- END i_open --> +<!-- BEGIN i_close --></em><!-- END i_close --> + +<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color --> + +<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: 116%;">{TEXT}</span><!-- END size --> + +<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img --> + +<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url --> + +<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email --> + +<!-- BEGIN flash --><object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}"><param name="movie" value="{URL}" /><param name="play" value="false" /><param name="loop" value="false" /><param name="quality" value="high" /><param name="allowScriptAccess" value="never" /><param name="allowNetworking" value="internal" /><embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed></object><!-- END flash --> diff --git a/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html new file mode 100644 index 0000000000..fad8d828fd --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/barplus/template/bbcode.html @@ -0,0 +1,40 @@ +<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open --> +<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default --> +<!-- BEGIN ulist_close --></ul><!-- END ulist_close --> + +<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open --> +<!-- BEGIN olist_close --></ol><!-- END olist_close --> + +<!-- BEGIN listitem --><li><!-- END listitem --> +<!-- BEGIN listitem_close --></li><!-- END listitem_close --> + +<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open --> +<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open --> +<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close --> + +<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open --> +<!-- BEGIN code_close --></code></div><!-- END code_close --> + +<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open --> +<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close --> + +<!-- BEGIN b_open --><b class="barplus"><!-- END b_open --> +<!-- BEGIN b_close --></b><!-- END b_close --> + +<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open --> +<!-- BEGIN u_close --></span><!-- END u_close --> + +<!-- BEGIN i_open --><em><!-- END i_open --> +<!-- BEGIN i_close --></em><!-- END i_close --> + +<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color --> + +<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: 116%;">{TEXT}</span><!-- END size --> + +<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img --> + +<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url --> + +<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email --> + +<!-- BEGIN flash --><object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}"><param name="movie" value="{URL}" /><param name="play" value="false" /><param name="loop" value="false" /><param name="quality" value="high" /><param name="allowScriptAccess" value="never" /><param name="allowNetworking" value="internal" /><embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed></object><!-- END flash --> diff --git a/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html new file mode 100644 index 0000000000..3e38d13a32 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/styles/foo/template/bbcode.html @@ -0,0 +1,40 @@ +<!-- BEGIN ulist_open --><ul style="list-style-type: {LIST_TYPE}"><!-- END ulist_open --> +<!-- BEGIN ulist_open_default --><ul><!-- END ulist_open_default --> +<!-- BEGIN ulist_close --></ul><!-- END ulist_close --> + +<!-- BEGIN olist_open --><ol style="list-style-type: {LIST_TYPE}"><!-- END olist_open --> +<!-- BEGIN olist_close --></ol><!-- END olist_close --> + +<!-- BEGIN listitem --><li><!-- END listitem --> +<!-- BEGIN listitem_close --></li><!-- END listitem_close --> + +<!-- BEGIN quote_username_open --><blockquote><div><cite>{USERNAME} {L_WROTE}{L_COLON}</cite><!-- END quote_username_open --> +<!-- BEGIN quote_open --><blockquote class="uncited"><div><!-- END quote_open --> +<!-- BEGIN quote_close --></div></blockquote><!-- END quote_close --> + +<!-- BEGIN code_open --><div class="codebox"><p>{L_CODE}{L_COLON} <a href="#" onclick="selectCode(this); return false;">{L_SELECT_ALL_CODE}</a></p><code><!-- END code_open --> +<!-- BEGIN code_close --></code></div><!-- END code_close --> + +<!-- BEGIN inline_attachment_open --><div class="inline-attachment"><!-- END inline_attachment_open --> +<!-- BEGIN inline_attachment_close --></div><!-- END inline_attachment_close --> + +<!-- BEGIN b_open --><strong><!-- END b_open --> +<!-- BEGIN b_close --></strong><!-- END b_close --> + +<!-- BEGIN u_open --><span style="text-decoration: underline"><!-- END u_open --> +<!-- BEGIN u_close --></span><!-- END u_close --> + +<!-- BEGIN i_open --><em><!-- END i_open --> +<!-- BEGIN i_close --></em><!-- END i_close --> + +<!-- BEGIN color --><span style="color: {COLOR}">{TEXT}</span><!-- END color --> + +<!-- BEGIN size --><span style="font-size: {SIZE}%; line-height: 116%;">{TEXT}</span><!-- END size --> + +<!-- BEGIN img --><img src="{URL}" class="postimage" alt="{L_IMAGE}" /><!-- END img --> + +<!-- BEGIN url --><a href="{URL}" class="postlink">{DESCRIPTION}</a><!-- END url --> + +<!-- BEGIN email --><a href="mailto:{EMAIL}">{DESCRIPTION}</a><!-- END email --> + +<!-- BEGIN flash --><object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="{WIDTH}" height="{HEIGHT}"><param name="movie" value="{URL}" /><param name="play" value="false" /><param name="loop" value="false" /><param name="quality" value="high" /><param name="allowScriptAccess" value="never" /><param name="allowNetworking" value="internal" /><embed src="{URL}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{WIDTH}" height="{HEIGHT}" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></embed></object><!-- END flash --> diff --git a/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml b/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml new file mode 100644 index 0000000000..55a2e689b6 --- /dev/null +++ b/tests/text_formatter/s9e/fixtures/unsafe_bbcode.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>xss=</value> +			<value></value> +			<value>1</value> +			<value>[xss={TEXT1}]{TEXT2}[/xss]</value> +			<value><![CDATA[<a href="{TEXT1}">{TEXT2}</a>]]></value> +			<value><\[/xss\]!ies]]></value> +			<value><![CDATA['[xss='.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/xss:$uid]']]></value> +			<value><\[/xss:$uid\]!s]]></value> +			<value><![CDATA[<a href="${1}">${2}</a>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_formatter/s9e/parser_test.php b/tests/text_formatter/s9e/parser_test.php new file mode 100644 index 0000000000..4b9bbf9bb2 --- /dev/null +++ b/tests/text_formatter/s9e/parser_test.php @@ -0,0 +1,258 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_textformatter_s9e_parser_test extends phpbb_test_case +{ +	public function test_load_from_cache() +	{ +		$mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') +		             ->disableOriginalConstructor() +		             ->getMock(); + +		$cache = $this->getMock('phpbb_mock_cache'); +		$cache->expects($this->once()) +		      ->method('get') +		      ->with('_foo_parser') +		      ->will($this->returnValue($mock)); + +		$factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') +		                ->disableOriginalConstructor() +		                ->getMock(); +		$factory->expects($this->never())->method('regenerate'); + +		$parser = new \phpbb\textformatter\s9e\parser( +			$cache, +			'_foo_parser', +			$factory, +			new phpbb_mock_event_dispatcher +		); +	} + +	public function test_use_from_cache() +	{ +		$mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') +		             ->disableOriginalConstructor() +		             ->getMock(); + +		$mock->expects($this->once()) +		     ->method('parse') +		     ->with('test') +		     ->will($this->returnValue('<t>test</t>')); + +		$cache = new phpbb_mock_cache; +		$cache->put('_foo_parser', $mock); + +		$factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') +		                ->disableOriginalConstructor() +		                ->getMock(); +		$factory->expects($this->never())->method('regenerate'); + +		$parser = new \phpbb\textformatter\s9e\parser( +			$cache, +			'_foo_parser', +			$factory, +			new phpbb_mock_event_dispatcher +		); + +		$this->assertSame('<t>test</t>', $parser->parse('test')); +	} + +	public function test_regenerate_on_cache_miss() +	{ +		$mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') +		             ->disableOriginalConstructor() +		             ->getMock(); + +		$mock->expects($this->once()) +		     ->method('parse') +		     ->with('test') +		     ->will($this->returnValue('<t>test</t>')); + +		$factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') +		                ->disableOriginalConstructor() +		                ->getMock(); +		$factory->expects($this->once()) +		        ->method('regenerate') +		        ->will($this->returnValue(array('parser' => $mock))); + +		$parser = new \phpbb\textformatter\s9e\parser( +			new phpbb_mock_cache, +			'_foo_parser', +			$factory, +			new phpbb_mock_event_dispatcher +		); + +		$this->assertSame('<t>test</t>', $parser->parse('test')); +	} + +	/** +	* @dataProvider get_options_tests() +	*/ +	public function test_options($adapter_method, $adapter_arg, $concrete_method, $concrete_arg) +	{ +		$mock = $this->getMockBuilder('s9e\\TextFormatter\\Parser') +		             ->setMethods(array($concrete_method)) +		             ->disableOriginalConstructor() +		             ->getMock(); +		foreach ((array) $concrete_arg as $i => $concrete_arg) +		{ +			$mock->expects($this->at($i)) +			     ->method($concrete_method) +			     ->with($concrete_arg); +		} + +		$cache = new phpbb_mock_cache; +		$cache->put('_foo_parser', $mock); + +		$factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') +		                ->disableOriginalConstructor() +		                ->getMock(); + +		$parser = new \phpbb\textformatter\s9e\parser( +			$cache, +			'_foo_parser', +			$factory, +			new phpbb_mock_event_dispatcher +		); + +		call_user_func_array(array($parser, $adapter_method), (array) $adapter_arg); +	} + +	public function get_options_tests() +	{ +		return array( +			array( +				'disable_bbcode', 'url', +				'disableTag',     'URL' +			), +			array( +				'disable_bbcodes', null, +				'disablePlugin',   'BBCodes' +			), +			array( +				'disable_magic_url', null, +				'disablePlugin',     array('Autoemail', 'Autolink') +			), +			array( +				'disable_smilies', null, +				'disablePlugin',   'Emoticons' +			), +			array( +				'enable_bbcode', 'url', +				'enableTag',     'URL' +			), +			array( +				'enable_bbcodes', null, +				'enablePlugin',   'BBCodes' +			), +			array( +				'enable_magic_url', null, +				'enablePlugin',     array('Autoemail', 'Autolink') +			), +			array( +				'enable_smilies', null, +				'enablePlugin',   'Emoticons' +			) +		); +	} + +	/** +	* @testdox The constructor triggers a core.text_formatter_s9e_parser_setup event +	*/ +	public function test_setup_event() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); +		$dispatcher +			->expects($this->once()) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_parser_setup', +				$this->callback(array($this, 'setup_event_callback')) +			) +			->will($this->returnArgument(1)); + +		new \phpbb\textformatter\s9e\parser( +			$container->get('cache.driver'), +			'_foo_parser', +			$container->get('text_formatter.s9e.factory'), +			$dispatcher +		); +	} + +	public function setup_event_callback($vars) +	{ +		return isset($vars['parser']) +			&& $vars['parser'] instanceof \phpbb\textformatter\s9e\parser; +	} + +	/** +	* @testdox parse() triggers a core.text_formatter_s9e_parse_before and core.text_formatter_s9e_parse_after events +	*/ +	public function test_parse_event() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); +		$dispatcher +			->expects($this->any()) +			->method('trigger_event') +			->will($this->returnArgument(1)); +		$dispatcher +			->expects($this->at(1)) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_parse_before', +				$this->callback(array($this, 'parse_before_event_callback')) +			) +			->will($this->returnArgument(1)); +		$dispatcher +			->expects($this->at(2)) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_parse_after', +				$this->callback(array($this, 'parse_after_event_callback')) +			) +			->will($this->returnArgument(1)); + +		$parser = new \phpbb\textformatter\s9e\parser( +			$container->get('cache.driver'), +			'_foo_parser', +			$container->get('text_formatter.s9e.factory'), +			$dispatcher +		); +		$parser->parse('...'); +	} + +	public function parse_before_event_callback($vars) +	{ +		return isset($vars['parser']) +			&& $vars['parser'] instanceof \phpbb\textformatter\s9e\parser +			&& isset($vars['text']) +			&& $vars['text'] === '...'; +	} + +	public function parse_after_event_callback($vars) +	{ +		return isset($vars['parser']) +			&& $vars['parser'] instanceof \phpbb\textformatter\s9e\parser +			&& isset($vars['xml']) +			&& $vars['xml'] === '<t>...</t>'; +	} + +	public function test_get_parser() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$parser = $container->get('text_formatter.parser'); +		$this->assertInstanceOf('s9e\\TextFormatter\\Parser', $parser->get_parser()); +	} +} diff --git a/tests/text_formatter/s9e/renderer_test.php b/tests/text_formatter/s9e/renderer_test.php new file mode 100644 index 0000000000..175b90fdc7 --- /dev/null +++ b/tests/text_formatter/s9e/renderer_test.php @@ -0,0 +1,481 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_textformatter_s9e_renderer_test extends phpbb_test_case +{ +	public function get_cache_dir() +	{ +		return __DIR__ . '/../../tmp/'; +	} + +	public function test_load_from_cache() +	{ +		// Save a fake renderer class in the cache dir +		file_put_contents( +			$this->get_cache_dir() . 'renderer_foo.php', +			'<?php class renderer_foo { public function setParameter() {} }' +		); + +		$cache = $this->getMock('phpbb_mock_cache'); +		$cache->expects($this->once()) +		      ->method('get') +		      ->with('_foo_renderer') +		      ->will($this->returnValue(array('class' => 'renderer_foo'))); + +		$factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') +		                ->disableOriginalConstructor() +		                ->getMock(); +		$factory->expects($this->never())->method('regenerate'); + +		$renderer = new \phpbb\textformatter\s9e\renderer( +			$cache, +			$this->get_cache_dir(), +			'_foo_renderer', +			$factory, +			new phpbb_mock_event_dispatcher +		); +	} + +	public function test_regenerate_on_cache_miss() +	{ +		$mock = $this->getMockForAbstractClass('s9e\\TextFormatter\\Renderer'); + +		$cache = $this->getMock('phpbb_mock_cache'); +		$cache->expects($this->once()) +		      ->method('get') +		      ->with('_foo_renderer') +		      ->will($this->returnValue(false)); + +		$factory = $this->getMockBuilder('phpbb\\textformatter\\s9e\\factory') +		                ->disableOriginalConstructor() +		                ->getMock(); +		$factory->expects($this->once()) +		        ->method('regenerate') +		        ->will($this->returnValue(array('parser' => $mock))); + +		$renderer = new \phpbb\textformatter\s9e\renderer( +			$cache, +			$this->get_cache_dir(), +			'_foo_renderer', +			$factory, +			new phpbb_mock_event_dispatcher +		); +	} + +	/** +	* @dataProvider get_options_cases +	*/ +	public function test_options($original, $expected, $calls) +	{ +		$container = new phpbb_mock_container_builder; +		$this->get_test_case_helpers()->set_s9e_services($container); + +		$renderer = $container->get('text_formatter.renderer'); + +		foreach ($calls as $method => $arg) +		{ +			$renderer->$method($arg); +		} + +		$this->assertSame($expected, $renderer->render($original)); +	} + +	public function get_options_cases() +	{ +		return array( +			array( +				'<t>apple</t>', +				'banana', +				array('set_viewcensors' => true) +			), +			array( +				'<t>apple</t>', +				'apple', +				array('set_viewcensors' => false) +			), +			array( +				'<r><FLASH height="456" url="http://example.org/foo.swf" width="123"><s>[flash=123,456]</s><URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL><e>[/flash]</e></FLASH></r>', +				'<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="123" height="456"><param name="movie" value="http://example.org/foo.swf"><param name="play" value="false"><param name="loop" value="false"><param name="quality" value="high"><param name="allowScriptAccess" value="never"><param name="allowNetworking" value="internal"><embed src="http://example.org/foo.swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="123" height="456" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></object>', +				array('set_viewflash' => true) +			), +			array( +				'<r><IMG src="http://example.org/foo.png"><s>[img]</s>http://example.org/foo.png<e>[/img]</e></IMG></r>', +				'<img src="http://example.org/foo.png" class="postimage" alt="Image">', +				array('set_viewimg' => true) +			), +			array( +				'<r><E>:)</E></r>', +				'<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile">', +				array('set_viewsmilies' => true) +			), +			array( +				'<r><E>:)</E></r>', +				':)', +				array('set_viewsmilies' => false) +			), +		); +	} + +	/** +	* @dataProvider get_default_options_cases +	*/ +	public function test_default_options($original, $expected, $setup = null) +	{ +		$container = new phpbb_mock_container_builder; + +		if (isset($setup)) +		{ +			$setup($container, $this); +		} + +		$this->get_test_case_helpers()->set_s9e_services($container); + +		$this->assertSame($expected, $container->get('text_formatter.renderer')->render($original)); +	} + +	public function get_default_options_cases() +	{ +		return array( +			array( +				'<t>apple</t>', +				'banana' +			), +			array( +				'<t>apple</t>', +				'banana', +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewcensors', false); + +					$phpbb_container->set('user', $user); +				} +			), +			array( +				'<t>apple</t>', +				'banana', +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewcensors', false); + +					$config = new \phpbb\config\config(array('allow_nocensors' => true)); + +					$phpbb_container->set('user', $user); +					$phpbb_container->set('config', $config); +				} +			), +			array( +				'<t>apple</t>', +				'apple', +				function ($phpbb_container, $test) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewcensors', false); + +					$config = new \phpbb\config\config(array('allow_nocensors' => true)); + +					$auth = $test->getMock('phpbb\\auth\\auth'); +					$auth->expects($test->any()) +					     ->method('acl_get') +					     ->with('u_chgcensors') +					     ->will($test->returnValue(true)); + +					$phpbb_container->set('user', $user); +					$phpbb_container->set('config', $config); +					$phpbb_container->set('auth', $auth); +				} +			), +			array( +				'<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>', +				'<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="123" height="456"><param name="movie" value="http://localhost/foo.swf"><param name="play" value="false"><param name="loop" value="false"><param name="quality" value="high"><param name="allowScriptAccess" value="never"><param name="allowNetworking" value="internal"><embed src="http://localhost/foo.swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="123" height="456" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></object>' +			), +			array( +				'<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>', +				'http://localhost/foo.swf', +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewflash', false); + +					$phpbb_container->set('user', $user); +				} +			), +			array( +				'<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>', +				'<img src="http://localhost/mrgreen.gif" class="postimage" alt="Image">' +			), +			array( +				'<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>', +				'<a href="http://localhost/mrgreen.gif" class="postlink">http://localhost/mrgreen.gif</a>', +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewimg', false); + +					$phpbb_container->set('user', $user); +				} +			), +			array( +				'<r><E>:)</E></r>', +				'<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile">' +			), +			array( +				'<r><E>:)</E></r>', +				':)', +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('smilies', false); + +					$phpbb_container->set('user', $user); +				} +			), +		); +	} + +	public function test_default_lang() +	{ +		global $phpbb_container; +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/default_lang.xml'); + +		$renderer = $phpbb_container->get('text_formatter.renderer'); + +		$this->assertSame('FOO_BAR', $renderer->render('<r><FOO/></r>')); +	} + +	/** +	* @dataProvider get_option_names +	*/ +	public function test_get_option($option_name) +	{ +		global $phpbb_container; +		$this->get_test_case_helpers()->set_s9e_services(); + +		$renderer = $phpbb_container->get('text_formatter.renderer'); + +		$renderer->{'set_' . $option_name}(false); +		$this->assertFalse($renderer->{'get_' . $option_name}()); +		$renderer->{'set_' . $option_name}(true); +		$this->assertTrue($renderer->{'get_' . $option_name}()); +	} + +	public function get_option_names() +	{ +		return array( +			array('viewcensors'), +			array('viewflash'), +			array('viewimg'), +			array('viewsmilies') +		); +	} + +	public function test_styles() +	{ +		global $phpbb_container; + +		$tests = array( +			1 => '<strong>bold</strong>', +			2 => '<b>bold</b>' +		); + +		global $phpbb_root_path, $phpEx; + +		foreach ($tests as $style_id => $expected) +		{ +			$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +			$lang = new \phpbb\language\language($lang_loader); +			$user = new \phpbb\user($lang, '\phpbb\datetime'); +			$user->style = array('style_id' => $style_id); + +			$phpbb_container = new phpbb_mock_container_builder; +			$phpbb_container->set('user', $user); + +			$this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/styles.xml', __DIR__ . '/fixtures/styles/'); + +			$renderer = $phpbb_container->get('text_formatter.renderer'); +			$this->assertSame( +				$expected, +				$renderer->render('<r><B><s>[b]</s>bold<e>[/b]</e></B></r>') +			); +		} +	} + +	public function test_style_inheritance1() +	{ +		global $phpbb_container, $phpbb_root_path, $phpEx; + +		// Style 3 inherits from 2 which inherits from 1. Only style 1 has a bbcode.html +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$user->style = array('style_id' => 3); + +		$phpbb_container = new phpbb_mock_container_builder; +		$phpbb_container->set('user', $user); + +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/'); + +		$renderer = $phpbb_container->get('text_formatter.renderer'); +		$this->assertSame( +			'<strong>bold</strong>', +			$renderer->render('<r><B><s>[b]</s>bold<e>[/b]</e></B></r>') +		); +	} + +	public function test_style_inheritance2() +	{ +		global $phpbb_container, $phpbb_root_path, $phpEx; + +		// Style 5 inherits from 4, but both have a bbcode.html +		$tests = array( +			4 => '<b>bold</b>', +			5 => '<b class="barplus">bold</b>' +		); + +		foreach ($tests as $style_id => $expected) +		{ +			$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +			$lang = new \phpbb\language\language($lang_loader); +			$user = new \phpbb\user($lang, '\phpbb\datetime'); +			$user->style = array('style_id' => $style_id); + +			$phpbb_container = new phpbb_mock_container_builder; +			$phpbb_container->set('user', $user); + +			$this->get_test_case_helpers()->set_s9e_services($phpbb_container, __DIR__ . '/fixtures/style_inheritance.xml', __DIR__ . '/fixtures/styles/'); + +			$renderer = $phpbb_container->get('text_formatter.renderer'); +			$this->assertSame( +				$expected, +				$renderer->render('<r><B><s>[b]</s>bold<e>[/b]</e></B></r>') +			); +		} +	} + +	/** +	* @testdox The constructor triggers a core.text_formatter_s9e_renderer_setup event +	*/ +	public function test_setup_event() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); +		$dispatcher +			->expects($this->once()) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_renderer_setup', +				$this->callback(array($this, 'setup_event_callback')) +			) +			->will($this->returnArgument(1)); + +		new \phpbb\textformatter\s9e\renderer( +			$container->get('cache.driver'), +			$container->getParameter('cache.dir'), +			'_foo_renderer', +			$container->get('text_formatter.s9e.factory'), +			$dispatcher +		); +	} + +	public function setup_event_callback($vars) +	{ +		return isset($vars['renderer']) +			&& $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer; +	} + +	/** +	* @testdox render() triggers a core.text_formatter_s9e_render_before and core.text_formatter_s9e_render_after events +	*/ +	public function test_render_event() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$dispatcher = $this->getMock('phpbb\\event\\dispatcher_interface'); +		$dispatcher +			->expects($this->any()) +			->method('trigger_event') +			->will($this->returnArgument(1)); +		$dispatcher +			->expects($this->at(1)) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_render_before', +				$this->callback(array($this, 'render_before_event_callback')) +			) +			->will($this->returnArgument(1)); +		$dispatcher +			->expects($this->at(2)) +			->method('trigger_event') +			->with( +				'core.text_formatter_s9e_render_after', +				$this->callback(array($this, 'render_after_event_callback')) +			) +			->will($this->returnArgument(1)); + +		$renderer = new \phpbb\textformatter\s9e\renderer( +			$container->get('cache.driver'), +			$container->getParameter('cache.dir'), +			'_foo_renderer', +			$container->get('text_formatter.s9e.factory'), +			$dispatcher +		); +		$renderer->render('<t>...</t>'); +	} + +	public function render_before_event_callback($vars) +	{ +		return isset($vars['renderer']) +			&& $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer +			&& isset($vars['xml']) +			&& $vars['xml'] === '<t>...</t>'; +	} + +	public function render_after_event_callback($vars) +	{ +		return isset($vars['html']) +			&& $vars['html'] === '...' +			&& isset($vars['renderer']) +			&& $vars['renderer'] instanceof \phpbb\textformatter\s9e\renderer; +	} + +	public function test_get_renderer() +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$renderer = $container->get('text_formatter.renderer'); +		$this->assertInstanceOf('s9e\\TextFormatter\\Renderer', $renderer->get_renderer()); +	} +} diff --git a/tests/text_formatter/s9e/utils_test.php b/tests/text_formatter/s9e/utils_test.php new file mode 100644 index 0000000000..719d3cda88 --- /dev/null +++ b/tests/text_formatter/s9e/utils_test.php @@ -0,0 +1,276 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_textformatter_s9e_utils_test extends phpbb_test_case +{ +	/** +	* @dataProvider get_unparse_tests +	*/ +	public function test_unparse($original, $expected) +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$utils     = $container->get('text_formatter.utils'); + +		$this->assertSame($expected, $utils->unparse($original)); +	} + +	public function get_unparse_tests() +	{ +		return array( +			array( +				'<t>Plain text</t>', +				'Plain text' +			), +			array( +				"<t>Multi<br/>\nline</t>", +				"Multi\nline" +			), +			array( +				'<r><B><s>[b]</s>bold<e>[/b]</e></B></r>', +				'[b]bold[/b]' +			) +		); +	} + +	/** +	* @dataProvider get_clean_formatting_tests +	*/ +	public function test_clean_formatting($original, $expected) +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$utils     = $container->get('text_formatter.utils'); + +		$this->assertSame($expected, $utils->clean_formatting($original)); +	} + +	public function get_clean_formatting_tests() +	{ +		return array( +			array( +				'<t>Plain text</t>', +				'Plain text' +			), +			array( +				"<t>Multi<br/>\nline</t>", +				"Multi\nline" +			), +			array( +				'<r><B><s>[b]</s>bold<e>[/b]</e></B></r>', +				' bold ' +			) +		); +	} + +	/** +	* @dataProvider get_outermost_quote_authors_tests +	*/ +	public function test_get_outermost_quote_authors($original, $expected) +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$utils     = $container->get('text_formatter.utils'); +		$parser    = $container->get('text_formatter.parser'); + +		$this->assertSame($expected, $utils->get_outermost_quote_authors($parser->parse($original))); +	} + +	public function get_outermost_quote_authors_tests() +	{ +		return array( +			array( +				'No quotes here', +				array() +			), +			array( +				'[quote="foo"]..[/quote] [quote]..[/quote]', +				array('foo') +			), +			array( +				'[quote=foo]..[/quote] [quote]..[/quote]', +				array('foo') +			), +			array( +				'[quote=foo]..[/quote] [quote=bar]..[/quote]', +				array('foo', 'bar') +			), +			array( +				'[quote=foo].[quote=baz]..[/quote].[/quote] [quote=bar]..[/quote]', +				array('foo', 'bar') +			), +		); +	} + +	/** +	* @dataProvider get_generate_quote_tests +	*/ +	public function test_generate_quote($text, $params, $expected) +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$utils     = $container->get('text_formatter.utils'); + +		$this->assertSame($expected, $utils->generate_quote($text, $params)); +	} + +	public function get_generate_quote_tests() +	{ +		return array( +			array( +				'...', +				array(), +				'[quote]...[/quote]', +			), +			array( +				'...', +				array('author' => 'Brian Kibler'), +				'[quote="Brian Kibler"]...[/quote]', +			), +			array( +				'...', +				array('author' => 'Brian "Brian Kibler" Kibler of Brian Kibler Gaming'), +				'[quote=\'Brian "Brian Kibler" Kibler of Brian Kibler Gaming\']...[/quote]', +			), +			array( +				'...', +				array('author' => "Brian Kibler Gaming's Brian Kibler"), +				'[quote="Brian Kibler Gaming\'s Brian Kibler"]...[/quote]', +			), +			array( +				'...', +				array('author' => "\\\"'"), +				'[quote="\\\\\\"\'"]...[/quote]', +			), +			array( +				'...', +				array('author' => 'Lots of doubles """ one single \' one backslash \\'), +				'[quote=\'Lots of doubles """ one single \\\' one backslash \\\\\']...[/quote]', +			), +			array( +				'...', +				array('author' => "Lots of singles ''' one double \" one backslash \\"), +				'[quote="Lots of singles \'\'\' one double \\" one backslash \\\\"]...[/quote]', +			), +			array( +				'...', +				array('author' => 'Defaults to doublequotes """\'\'\''), +				'[quote="Defaults to doublequotes \\"\\"\\"\'\'\'"]...[/quote]', +			), +			array( +				'...', +				array( +					'author'  => 'user', +					'post_id' => 123, +					'url'     => 'http://example.org' +				), +				'[quote=user post_id=123 url=http://example.org]...[/quote]', +			), +			array( +				'...', +				array( +					'author'  => 'user', +					'post_id' => 123, +					'user_id' => ANONYMOUS +				), +				'[quote=user post_id=123]...[/quote]', +			), +			array( +				'...', +				array('author'  => ' '), +				'[quote=" "]...[/quote]', +			), +			array( +				'...', +				array('author'  => 'foo bar'), +				'[quote="foo bar"]...[/quote]', +			), +			array( +				'...', +				array('author'  => '\\'), +				'[quote="\\\\"]...[/quote]', +			), +			array( +				'...', +				array('author'  => '[quote="foo"]'), +				'[quote=\'[quote="foo"]\']...[/quote]', +			), +			array( +				'...', +				array('author'  => '""'), +				'[quote=\'""\']...[/quote]', +			), +			array( +				'...', +				array('author'  => "''"), +				'[quote="\'\'"]...[/quote]', +			), +			array( +				'This is a long quote that is definitely going to exceed 80 characters', +				array(), +				"[quote]\nThis is a long quote that is definitely going to exceed 80 characters\n[/quote]", +			), +			array( +				'  This is a short quote on its own line  ', +				array(), +				'[quote]This is a short quote on its own line[/quote]', +			), +			array( +				"This is a short quote\non two lines", +				array(), +				"[quote]\nThis is a short quote\non two lines\n[/quote]", +			), +		); +	} + +	/** +	* @dataProvider get_remove_bbcode_tests +	*/ +	public function test_remove_bbcode($original, $name, $depth, $expected) +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(); +		$parser    = $container->get('text_formatter.parser'); +		$utils     = $container->get('text_formatter.utils'); + +		$parsed = $parser->parse($original); +		$actual = $utils->unparse($utils->remove_bbcode($parsed, $name, $depth)); + +		$this->assertSame($expected, $actual); +	} + +	public function get_remove_bbcode_tests() +	{ +		return array( +			array( +				'Plain text', +				'b', +				1, +				'Plain text' +			), +			array( +				'[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]', +				'quote', +				0, +				'[b]bold[/b]', +			), +			array( +				'[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]', +				'quote', +				1, +				'[quote="u0"]q0[/quote][b]bold[/b]', +			), +			array( +				'[quote="u0"][quote="u1"][quote="u2"]q2[/quote]q1[/quote]q0[/quote][b]bold[/b]', +				'quote', +				2, +				'[quote="u0"][quote="u1"]q1[/quote]q0[/quote][b]bold[/b]', +			), +		); +	} +} diff --git a/tests/text_processing/censor_text_test.php b/tests/text_processing/censor_text_test.php index 983a5ba2d3..eda2bbb1b3 100644 --- a/tests/text_processing/censor_text_test.php +++ b/tests/text_processing/censor_text_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_text_processing_censor_text_test extends phpbb_test_case  {  	public function censor_text_data() diff --git a/tests/text_processing/decode_message_test.php b/tests/text_processing/decode_message_test.php new file mode 100644 index 0000000000..e2402e721a --- /dev/null +++ b/tests/text_processing/decode_message_test.php @@ -0,0 +1,113 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_text_processing_decode_message_test extends phpbb_test_case +{ +	public function setUp() +	{ +		parent::setUp(); + +		global $phpbb_dispatcher; + +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +	} + +	/** +	* @dataProvider get_legacy_tests +	*/ +	public function test_legacy($original, $expected, $bbcode_uid = '') +	{ +		$actual = $original; +		decode_message($actual, $bbcode_uid); + +		$this->assertSame($expected, $actual); +	} + +	public function get_legacy_tests() +	{ +		return array( +			array( +				"&<>"'", +				"&<>"'" +			), +			array( +				'<!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) -->', +				':)' +			), +			array( +				'<!-- w --><a class="postlink" href="http://www.phpbb.com">www.phpbb.com</a><!-- w -->', +				'www.phpbb.com' +			), +			array( +				'<!-- m --><a class="postlink" href="http://www.phpbb.com">http://www.phpbb.com</a><!-- m -->', +				'http://www.phpbb.com' +			), +			array( +				'<!-- m --><a class="postlink" href="http://www.phpbb.com">this is just text</a><!-- m -->', +				'http://www.phpbb.com' +			), +			array( +				'<!-- m --><a class="postlink" href="http://www.phpbb.com/some/more/link/that/is/shortened">http://www.phpbb.com/some/ ... /shortened</a><!-- m -->', +				'http://www.phpbb.com/some/more/link/that/is/shortened' +			), +			/** +			* Fails as per PHPBB3-8420 +			* @link http://tracker.phpbb.com/browse/PHPBB3-8420 +			* +			array( +				'[url=http://example.com:2cpxwbdy]<!-- s:arrow: --><img src="{SMILIES_PATH}/icon_arrow.gif" alt=":arrow:" title="Arrow" /><!-- s:arrow: --> here[/url:2cpxwbdy]', +				'[url=http://example.com] :arrow: here[/url]', +				'2cpxwbdy' +			), +			*/ +		); +	} + +	/** +	* @dataProvider get_text_formatter_tests +	*/ +	public function test_text_formatter($original, $expected) +	{ +		$this->get_test_case_helpers()->set_s9e_services(); + +		$actual = $original; +		decode_message($actual); + +		$this->assertSame($expected, $actual); +	} + +	public function get_text_formatter_tests() +	{ +		return array( +			array( +				"<t>&<>\"'", +				"&<>"'" +			), +			array( +				'<r><E>:)</E></r>', +				':)' +			), +			array( +				"<t>a<br/>\nb</t>", +				"a\nb" +			), +			/** +			* @link http://tracker.phpbb.com/browse/PHPBB3-8420 +			*/ +			array( +				'<r><URL url="http://example.com"><s>[url=http://example.com]</s> <E>:arrow:</E> here<e>[/url]</e></URL></r>', +				'[url=http://example.com] :arrow: here[/url]' +			), +		); +	} +} diff --git a/tests/text_processing/fixtures/empty.xml b/tests/text_processing/fixtures/empty.xml new file mode 100644 index 0000000000..d8206ad124 --- /dev/null +++ b/tests/text_processing/fixtures/empty.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +</dataset> diff --git a/tests/text_processing/fixtures/smilies.xml b/tests/text_processing/fixtures/smilies.xml new file mode 100644 index 0000000000..25b2e60836 --- /dev/null +++ b/tests/text_processing/fixtures/smilies.xml @@ -0,0 +1,443 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>1</value> +			<value>:D</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>1</value> +			<value>1</value> +		</row> +		<row> +			<value>2</value> +			<value>:-D</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>2</value> +			<value>1</value> +		</row> +		<row> +			<value>3</value> +			<value>:grin:</value> +			<value>Very Happy</value> +			<value>icon_e_biggrin.gif</value> +			<value>15</value> +			<value>17</value> +			<value>3</value> +			<value>1</value> +		</row> +		<row> +			<value>4</value> +			<value>:)</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>4</value> +			<value>1</value> +		</row> +		<row> +			<value>5</value> +			<value>:-)</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>5</value> +			<value>1</value> +		</row> +		<row> +			<value>6</value> +			<value>:smile:</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>6</value> +			<value>1</value> +		</row> +		<row> +			<value>7</value> +			<value>;)</value> +			<value>Wink</value> +			<value>icon_e_wink.gif</value> +			<value>15</value> +			<value>17</value> +			<value>7</value> +			<value>1</value> +		</row> +		<row> +			<value>8</value> +			<value>;-)</value> +			<value>Wink</value> +			<value>icon_e_wink.gif</value> +			<value>15</value> +			<value>17</value> +			<value>8</value> +			<value>1</value> +		</row> +		<row> +			<value>9</value> +			<value>:wink:</value> +			<value>Wink</value> +			<value>icon_e_wink.gif</value> +			<value>15</value> +			<value>17</value> +			<value>9</value> +			<value>1</value> +		</row> +		<row> +			<value>10</value> +			<value>:(</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>10</value> +			<value>1</value> +		</row> +		<row> +			<value>11</value> +			<value>:-(</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>11</value> +			<value>1</value> +		</row> +		<row> +			<value>12</value> +			<value>:sad:</value> +			<value>Sad</value> +			<value>icon_e_sad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>12</value> +			<value>1</value> +		</row> +		<row> +			<value>13</value> +			<value>:o</value> +			<value>Surprised</value> +			<value>icon_e_surprised.gif</value> +			<value>15</value> +			<value>17</value> +			<value>13</value> +			<value>1</value> +		</row> +		<row> +			<value>14</value> +			<value>:-o</value> +			<value>Surprised</value> +			<value>icon_e_surprised.gif</value> +			<value>15</value> +			<value>17</value> +			<value>14</value> +			<value>1</value> +		</row> +		<row> +			<value>15</value> +			<value>:eek:</value> +			<value>Surprised</value> +			<value>icon_e_surprised.gif</value> +			<value>15</value> +			<value>17</value> +			<value>15</value> +			<value>1</value> +		</row> +		<row> +			<value>16</value> +			<value>:shock:</value> +			<value>Shocked</value> +			<value>icon_eek.gif</value> +			<value>15</value> +			<value>17</value> +			<value>16</value> +			<value>1</value> +		</row> +		<row> +			<value>17</value> +			<value>:?</value> +			<value>Confused</value> +			<value>icon_e_confused.gif</value> +			<value>15</value> +			<value>17</value> +			<value>17</value> +			<value>1</value> +		</row> +		<row> +			<value>18</value> +			<value>:-?</value> +			<value>Confused</value> +			<value>icon_e_confused.gif</value> +			<value>15</value> +			<value>17</value> +			<value>18</value> +			<value>1</value> +		</row> +		<row> +			<value>19</value> +			<value>:???:</value> +			<value>Confused</value> +			<value>icon_e_confused.gif</value> +			<value>15</value> +			<value>17</value> +			<value>19</value> +			<value>1</value> +		</row> +		<row> +			<value>20</value> +			<value>8-)</value> +			<value>Cool</value> +			<value>icon_cool.gif</value> +			<value>15</value> +			<value>17</value> +			<value>20</value> +			<value>1</value> +		</row> +		<row> +			<value>21</value> +			<value>:cool:</value> +			<value>Cool</value> +			<value>icon_cool.gif</value> +			<value>15</value> +			<value>17</value> +			<value>21</value> +			<value>1</value> +		</row> +		<row> +			<value>22</value> +			<value>:lol:</value> +			<value>Laughing</value> +			<value>icon_lol.gif</value> +			<value>15</value> +			<value>17</value> +			<value>22</value> +			<value>1</value> +		</row> +		<row> +			<value>23</value> +			<value>:x</value> +			<value>Mad</value> +			<value>icon_mad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>23</value> +			<value>1</value> +		</row> +		<row> +			<value>24</value> +			<value>:-x</value> +			<value>Mad</value> +			<value>icon_mad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>24</value> +			<value>1</value> +		</row> +		<row> +			<value>25</value> +			<value>:mad:</value> +			<value>Mad</value> +			<value>icon_mad.gif</value> +			<value>15</value> +			<value>17</value> +			<value>25</value> +			<value>1</value> +		</row> +		<row> +			<value>26</value> +			<value>:P</value> +			<value>Razz</value> +			<value>icon_razz.gif</value> +			<value>15</value> +			<value>17</value> +			<value>26</value> +			<value>1</value> +		</row> +		<row> +			<value>27</value> +			<value>:-P</value> +			<value>Razz</value> +			<value>icon_razz.gif</value> +			<value>15</value> +			<value>17</value> +			<value>27</value> +			<value>1</value> +		</row> +		<row> +			<value>28</value> +			<value>:razz:</value> +			<value>Razz</value> +			<value>icon_razz.gif</value> +			<value>15</value> +			<value>17</value> +			<value>28</value> +			<value>1</value> +		</row> +		<row> +			<value>29</value> +			<value>:oops:</value> +			<value>Embarrassed</value> +			<value>icon_redface.gif</value> +			<value>15</value> +			<value>17</value> +			<value>29</value> +			<value>1</value> +		</row> +		<row> +			<value>30</value> +			<value>:cry:</value> +			<value>Crying or Very Sad</value> +			<value>icon_cry.gif</value> +			<value>15</value> +			<value>17</value> +			<value>30</value> +			<value>1</value> +		</row> +		<row> +			<value>31</value> +			<value>:evil:</value> +			<value>Evil or Very Mad</value> +			<value>icon_evil.gif</value> +			<value>15</value> +			<value>17</value> +			<value>31</value> +			<value>1</value> +		</row> +		<row> +			<value>32</value> +			<value>:twisted:</value> +			<value>Twisted Evil</value> +			<value>icon_twisted.gif</value> +			<value>15</value> +			<value>17</value> +			<value>32</value> +			<value>1</value> +		</row> +		<row> +			<value>33</value> +			<value>:roll:</value> +			<value>Rolling Eyes</value> +			<value>icon_rolleyes.gif</value> +			<value>15</value> +			<value>17</value> +			<value>33</value> +			<value>1</value> +		</row> +		<row> +			<value>34</value> +			<value>:!:</value> +			<value>Exclamation</value> +			<value>icon_exclaim.gif</value> +			<value>15</value> +			<value>17</value> +			<value>34</value> +			<value>1</value> +		</row> +		<row> +			<value>35</value> +			<value>:?:</value> +			<value>Question</value> +			<value>icon_question.gif</value> +			<value>15</value> +			<value>17</value> +			<value>35</value> +			<value>1</value> +		</row> +		<row> +			<value>36</value> +			<value>:idea:</value> +			<value>Idea</value> +			<value>icon_idea.gif</value> +			<value>15</value> +			<value>17</value> +			<value>36</value> +			<value>1</value> +		</row> +		<row> +			<value>37</value> +			<value>:arrow:</value> +			<value>Arrow</value> +			<value>icon_arrow.gif</value> +			<value>15</value> +			<value>17</value> +			<value>37</value> +			<value>1</value> +		</row> +		<row> +			<value>38</value> +			<value>:|</value> +			<value>Neutral</value> +			<value>icon_neutral.gif</value> +			<value>15</value> +			<value>17</value> +			<value>38</value> +			<value>1</value> +		</row> +		<row> +			<value>39</value> +			<value>:-|</value> +			<value>Neutral</value> +			<value>icon_neutral.gif</value> +			<value>15</value> +			<value>17</value> +			<value>39</value> +			<value>1</value> +		</row> +		<row> +			<value>40</value> +			<value>:mrgreen:</value> +			<value>Mr. Green</value> +			<value>icon_mrgreen.gif</value> +			<value>15</value> +			<value>17</value> +			<value>40</value> +			<value>1</value> +		</row> +		<row> +			<value>41</value> +			<value>:geek:</value> +			<value>Geek</value> +			<value>icon_e_geek.gif</value> +			<value>17</value> +			<value>17</value> +			<value>41</value> +			<value>1</value> +		</row> +		<row> +			<value>42</value> +			<value>:ugeek:</value> +			<value>Uber Geek</value> +			<value>icon_e_ugeek.gif</value> +			<value>17</value> +			<value>18</value> +			<value>42</value> +			<value>1</value> +		</row> +		<row> +			<value>43</value> +			<value>8)</value> +			<value>8)</value> +			<value>custom.gif</value> +			<value>17</value> +			<value>18</value> +			<value>42</value> +			<value>1</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/generate_text_for_display_test.php b/tests/text_processing/generate_text_for_display_test.php index 057416da33..b8b5b18561 100644 --- a/tests/text_processing/generate_text_for_display_test.php +++ b/tests/text_processing/generate_text_for_display_test.php @@ -11,11 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -require_once dirname(__FILE__) . '/../mock/user.php'; -require_once dirname(__FILE__) . '/../mock/cache.php'; -  class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_case  {  	public function setUp() @@ -24,21 +19,195 @@ class phpbb_text_processing_generate_text_for_display_test extends phpbb_test_ca  		parent::setUp(); +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher; +		$config = new \phpbb\config\config(array()); +		set_config(null, null, null, $config); +	} + +	/** +	* @dataProvider get_legacy_tests +	*/ +	public function test_legacy($original, $expected, $uid = '', $bitfield = '', $flags = 0, $censor_text = true) +	{ +		global $cache, $user; + +		global $phpbb_root_path, $phpEx; +  		$cache = new phpbb_mock_cache; +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime'); +		$user->optionset('viewcensors', true); +		$user->optionset('viewflash', true); +		$user->optionset('viewimg', true); +		$user->optionset('viewsmilies', true); + +		$actual = generate_text_for_display($original, $uid, $bitfield, $flags, $censor_text); + +		$this->assertSame($expected, $actual); +	} + +	public function get_legacy_tests() +	{ +		return array( +			array( +				'', +				'' +			), +			array( +				'0', +				'0' +			), +		); +	} + +	public function test_censor_is_restored() +	{ +		global $phpbb_container; + +		$phpbb_container = new phpbb_mock_container_builder; + +		global $phpbb_root_path, $phpEx; -		$user = new phpbb_mock_user; +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +		$user = new \phpbb\user($lang, '\phpbb\datetime');  		$user->optionset('viewcensors', false); -		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		$config = new \phpbb\config\config(array('allow_nocensors' => true)); + +		$auth = $this->getMock('phpbb\\auth\\auth'); +		$auth->expects($this->any()) +			 ->method('acl_get') +			 ->with('u_chgcensors') +			 ->will($this->returnValue(true)); + +		$phpbb_container->set('user', $user); +		$phpbb_container->set('config', $config); +		$phpbb_container->set('auth', $auth); + +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container); +		$renderer = $phpbb_container->get('text_formatter.renderer'); + +		$original = '<r><CENSOR with="banana">apple</CENSOR></r>'; + +		$renderer->set_viewcensors(false); +		$this->assertSame('apple', $renderer->render($original)); +		$renderer->set_viewcensors(true); +		$this->assertSame('banana', $renderer->render($original)); +		$this->assertSame('apple', generate_text_for_display($original, '', '', 0, false)); +		$this->assertSame('banana', $renderer->render($original), 'The original setting was not restored'); + +		$renderer->set_viewcensors(false); +		$this->assertSame('apple', $renderer->render($original)); +		$this->assertSame('banana', generate_text_for_display($original, '', '', 0, truee)); +		$this->assertSame('apple', $renderer->render($original), 'The original setting was not restored');  	} -	public function test_empty_string() +	/** +	* @dataProvider get_text_formatter_tests +	*/ +	public function test_text_formatter($original, $expected, $censor_text = true, $setup = null)  	{ -		$this->assertSame('', generate_text_for_display('', '', '', 0)); +		global $phpbb_container; + +		$phpbb_container = new phpbb_mock_container_builder; + +		if (isset($setup)) +		{ +			$setup($phpbb_container, $this); +		} + +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container); + +		$this->assertSame($expected, generate_text_for_display($original, '', '', 0, $censor_text));  	} -	public function test_zero_string() +	public function get_text_formatter_tests()  	{ -		$this->assertSame('0', generate_text_for_display('0', '', '', 0)); +		return array( +			array( +				'<t>Plain text</t>', +				'Plain text' +			), +			array( +				'<r>Hello <URL url="http://example.org"><s>[url=http://example.org]</s>world<e>[/url]</e></URL></r>', +				'Hello <a href="http://example.org" class="postlink">world</a>' +			), +			array( +				'<t>&<>"\'</t>', +				'&<>"\'' +			), +			array( +				'<r><CENSOR with="banana">apple</CENSOR></r>', +				'banana', +				true +			), +			array( +				'<r><CENSOR with="banana">apple</CENSOR></r>', +				'apple', +				false +			), +			array( +				'<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>', +				'<object classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://active.macromedia.com/flash2/cabs/swflash.cab#version=5,0,0,0" width="123" height="456"><param name="movie" value="http://localhost/foo.swf"><param name="play" value="false"><param name="loop" value="false"><param name="quality" value="high"><param name="allowScriptAccess" value="never"><param name="allowNetworking" value="internal"><embed src="http://localhost/foo.swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="123" height="456" play="false" loop="false" quality="high" allowscriptaccess="never" allownetworking="internal"></object>' +			), +			array( +				'<r><FLASH url="http://localhost/foo.swf" width="123" height="456"><s>[flash=123,456]</s>http://localhost/foo.swf<e>[/flash]</e></FLASH></r>', +				'http://localhost/foo.swf', +				true, +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewflash', false); + +					$phpbb_container->set('user', $user); +				} +			), +			array( +				'<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>', +				'<img src="http://localhost/mrgreen.gif" class="postimage" alt="Image">' +			), +			array( +				'<r><IMG src="http://localhost/mrgreen.gif"><s>[img]</s><URL url="http://localhost/mrgreen.gif">http://localhost/mrgreen.gif</URL><e>[/img]</e></IMG></r>', +				'<a href="http://localhost/mrgreen.gif" class="postlink">http://localhost/mrgreen.gif</a>', +				true, +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('viewimg', false); + +					$phpbb_container->set('user', $user); +				} +			), +			array( +				'<r><E>:)</E></r>', +				'<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile">' +			), +			array( +				'<r><E>:)</E></r>', +				':)', +				true, +				function ($phpbb_container) +				{ +					global $phpbb_root_path, $phpEx; + +					$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +					$lang = new \phpbb\language\language($lang_loader); +					$user = new \phpbb\user($lang, '\phpbb\datetime'); +					$user->optionset('smilies', false); + +					$phpbb_container->set('user', $user); +				} +			), +		);  	}  } diff --git a/tests/text_processing/generate_text_for_edit_test.php b/tests/text_processing/generate_text_for_edit_test.php new file mode 100644 index 0000000000..8258a196f5 --- /dev/null +++ b/tests/text_processing/generate_text_for_edit_test.php @@ -0,0 +1,89 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_text_processing_generate_text_for_edit_test extends phpbb_test_case +{ +	/** +	* @dataProvider get_legacy_tests +	*/ +	public function test_legacy($original, $expected, $uid = '', $flags = 0) +	{ +		global $cache, $user, $phpbb_dispatcher; + +		$cache = new phpbb_mock_cache; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher; + +		$user = new phpbb_mock_user; +		$user->optionset('viewcensors', false); + +		$return = generate_text_for_edit($original, $uid, $flags); + +		$this->assertSame($expected, $return['text']); +	} + +	public function get_legacy_tests() +	{ +		return array( +			array( +				'', +				'' +			), +			array( +				'0', +				'0' +			), +			array( +				'Hello [url=http://example.org:1f4coh9x]world[/url:1f4coh9x] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) -->', +				'Hello [url=http://example.org]world[/url] :)', +				'1f4coh9x', +				0 +			), +			array( +				"&<>"'", +				"&<>"'" +			) +		); +	} + +	/** +	* @dataProvider get_text_formatter_tests +	*/ +	public function test_text_formatter($original, $expected) +	{ +		global $phpbb_dispatcher; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher; +		$this->get_test_case_helpers()->set_s9e_services(); + +		$return = generate_text_for_edit($original, '', 0); + +		$this->assertSame($expected, $return['text']); +	} + +	public function get_text_formatter_tests() +	{ +		return array( +			array( +				'<t>Plain text</t>', +				'Plain text' +			), +			array( +				'<r>Hello <URL url="http://example.org"><s>[url=http://example.org]</s>world<e>[/url]</e></URL> <E>:)</E></r>', +				'Hello [url=http://example.org]world[/url] :)' +			), +			array( +				'<t>&<>"\'</t>', +				"&<>"'" +			) +		); +	} +} diff --git a/tests/text_processing/generate_text_for_storage_test.php b/tests/text_processing/generate_text_for_storage_test.php new file mode 100644 index 0000000000..f0588fec4f --- /dev/null +++ b/tests/text_processing/generate_text_for_storage_test.php @@ -0,0 +1,178 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_text_processing_generate_text_for_storage_test extends phpbb_test_case +{ +	public function setUp() +	{ +		global $config, $phpbb_container, $phpbb_dispatcher; + +		parent::setUp(); + +		$config = new \phpbb\config\config(array()); +		set_config(null, null, null, $config); + +		$phpbb_container = new phpbb_mock_container_builder; +		$phpbb_container->set('config', $config); +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container); + +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher; +	} + +	/** +	* @dataProvider get_text_formatter_tests +	*/ +	public function test_text_formatter($original, $expected, $allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode, $setup = null) +	{ +		$actual   = $original; +		$uid      = ''; +		$bitfield = ''; +		$flags    = 0; + +		if (isset($setup)) +		{ +			$setup(); +		} + +		generate_text_for_storage($actual, $uid, $bitfield, $flags, $allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode); + +		$this->assertSame($expected, $actual); +	} + +	public function get_text_formatter_tests() +	{ +		return array( +			array( +				'Hello world', +				'<t>Hello world</t>', +				true, +				true, +				true, +				true, +				true, +				true, +				true, +			), +			array( +				'Hello [url=http://example.org]world[/url] :)', +				'<r>Hello <URL url="http://example.org"><s>[url=http://example.org]</s>world<e>[/url]</e></URL> <E>:)</E></r>', +				true, +				true, +				true, +				true, +				true, +				true, +				true, +			), +			array( +				'&<>"\'', +				'<t>&<>"\'</t>', +				true, +				true, +				true, +				true, +				true, +				true, +				true, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<t>[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</t>', +				false, +				false, +				false, +				false, +				false, +				false, +				false, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</r>', +				true, +				false, +				false, +				false, +				false, +				false, +				false, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r>[b]..[/b] <URL url="http://example.org">http://example.org</URL> :) [img]<URL url="http://example.org/img.png">http://example.org/img.png</URL>[/img] [flash=123,123]<URL url="http://example.org/flash.swf">http://example.org/flash.swf</URL>[/flash] [quote]...[/quote] [url]<URL url="http://example.org">http://example.org</URL>[/url]</r>', +				false, +				true, +				false, +				false, +				false, +				false, +				true, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r>[b]..[/b] http://example.org <E>:)</E> [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</r>', +				false, +				false, +				true, +				false, +				false, +				false, +				false, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) <IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG> [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]</r>', +				true, +				false, +				false, +				true, +				false, +				false, +				false, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] <FLASH height="123" url="http://example.org/flash.swf" width="123"><s>[flash=123,123]</s>http://example.org/flash.swf<e>[/flash]</e></FLASH> [quote]...[/quote] [url]http://example.org[/url]</r>', +				true, +				false, +				false, +				false, +				true, +				false, +				false, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] <QUOTE><s>[quote]</s>...<e>[/quote]</e></QUOTE> [url]http://example.org[/url]</r>', +				true, +				false, +				false, +				false, +				false, +				true, +				false, +			), +			array( +				'[b]..[/b] http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] [url]http://example.org[/url]', +				'<r><B><s>[b]</s>..<e>[/b]</e></B> http://example.org :) [img]http://example.org/img.png[/img] [flash=123,123]http://example.org/flash.swf[/flash] [quote]...[/quote] <URL url="http://example.org"><s>[url]</s>http://example.org<e>[/url]</e></URL></r>', +				true, +				false, +				false, +				false, +				false, +				false, +				true, +			), +		); +	} +} diff --git a/tests/text_processing/make_clickable_test.php b/tests/text_processing/make_clickable_test.php index 95e304dd97..3c8539c612 100644 --- a/tests/text_processing/make_clickable_test.php +++ b/tests/text_processing/make_clickable_test.php @@ -11,9 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; -  class phpbb_text_processing_make_clickable_test extends phpbb_test_case  {  	public function make_clickable_data() diff --git a/tests/text_processing/message_parser_test.php b/tests/text_processing/message_parser_test.php new file mode 100644 index 0000000000..a3dbf644f6 --- /dev/null +++ b/tests/text_processing/message_parser_test.php @@ -0,0 +1,540 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../../phpBB/includes/bbcode.php'; +require_once __DIR__ . '/../../phpBB/includes/message_parser.php'; + +class phpbb_text_processing_message_parser_test extends phpbb_test_case +{ +	public static function setUpBeforeClass() +	{ +		parent::setUpBeforeClass(); + +		// Set up an intercepting proxy for getimagesize() calls +		stream_wrapper_unregister('http'); +		stream_wrapper_register('http', __CLASS__ . '_proxy'); +	} + +	public static function tearDownAfterClass() +	{ +		parent::tearDownAfterClass(); +		stream_wrapper_restore('http'); +	} + +	protected function prepare_s9e_services($setup = null) +	{ +		global $config, $phpbb_container, $user; + +		$config = new \phpbb\config\config(array('max_poll_options' => 999)); + +		$map = array( +			array('MAX_FLASH_HEIGHT_EXCEEDED', 123, 'Your flash files may only be up to 123 pixels high.'), +			array('MAX_FLASH_WIDTH_EXCEEDED', 456, 'Your flash files may only be up to 456 pixels wide.'), +			array('MAX_FONT_SIZE_EXCEEDED', 120, 'You may only use fonts up to size 120.'), +			array('MAX_FONT_SIZE_EXCEEDED', 200, 'You may only use fonts up to size 200.'), +			array('MAX_IMG_HEIGHT_EXCEEDED', 12, 'Your images may only be up to 12 pixels high.'), +			array('MAX_IMG_WIDTH_EXCEEDED', 34, 'Your images may only be up to 34 pixels wide.'), +			array('TOO_MANY_SMILIES', 3, 'Your message contains too many smilies. The maximum number of smilies allowed is 3.'), +			array('TOO_MANY_URLS', 2, 'Your message contains too many URLs. The maximum number of URLs allowed is 2.'), +			array('UNAUTHORISED_BBCODE', '[flash]', 'You cannot use certain BBCodes: [flash].'), +			array('UNAUTHORISED_BBCODE', '[img]', 'You cannot use certain BBCodes: [img].'), +			array('UNAUTHORISED_BBCODE', '[quote]', 'You cannot use certain BBCodes: [quote].'), +			array('UNAUTHORISED_BBCODE', '[url]', 'You cannot use certain BBCodes: [url].'), +			array('UNABLE_GET_IMAGE_SIZE', 'It was not possible to determine the dimensions of the image.'), +		); + +		$user = $this->getMockBuilder('phpbb\\user')->disableOriginalConstructor()->getMock(); +		$user->expects($this->any()) +		     ->method('lang') +		     ->will($this->returnValueMap($map)); + +		$user->data = array( +			'is_bot' => false, +			'is_registered' => true, +			'user_id' => 2, +		); +		$user->style = array('style_id' => 1); + +		$user->lang = array( +			'NO_POLL_TITLE' => 'You have to enter a poll title.', +			'POLL_TITLE_TOO_LONG' => 'The poll title must contain fewer than 100 characters.', +			'POLL_TITLE_COMP_TOO_LONG' => 'The parsed size of your poll title is too large, consider removing BBCodes or smilies.', +			'TOO_FEW_POLL_OPTIONS' => 'You must enter at least two poll options.', +			'TOO_MANY_POLL_OPTIONS' => 'You have tried to enter too many poll options.', +			'TOO_MANY_USER_OPTIONS' => 'You cannot specify more options per user than existing poll options.', +		); + +		$phpbb_container = new phpbb_mock_container_builder; +		$phpbb_container->set('user', $user); +		$phpbb_container->set('config', $config); + +		if (isset($setup)) +		{ +			$setup($phpbb_container, $this); +		} + +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container); +	} + +	/** +	* @dataProvider get_test_polls +	*/ +	public function test_parse_poll($poll, $expected, $warn_msg = array()) +	{ +		$this->prepare_s9e_services(); + +		$message_parser = new parse_message('Me[i]s[/i]sage'); + +		// Add some default values +		$poll += array( +			'poll_length'		=> 123, +			'poll_start'		=> 123, +			'poll_last_vote'	=> 123, +			'poll_vote_change'	=> true, +			'enable_bbcode'		=> true, +			'enable_urls'		=> true, +			'enable_smilies'	=> true, +			'img_status'		=> true +		); + +		$message_parser->parse_poll($poll); +		$this->assertSame($expected, array_intersect_key($poll, $expected)); + +		$this->assertSame( +			'<r>Me<I><s>[i]</s>s<e>[/i]</e></I>sage</r>', +			$message_parser->parse(true, true, true, true, true, true, true, false) +		); + +		$this->assertSame($warn_msg, $message_parser->warn_msg); +	} + +	public function get_test_polls() +	{ +		return array( +			array( +				array( +					'poll_title' => 'foo [b]bar[/b] baz', +					'poll_option_text' => "[i]foo[/i]\nbar\n[i]baz[/i]", +					'poll_max_options'	=> 3, +					'poll_options_size' => 3 +				), +				array( +					'poll_title' => '<r>foo <B><s>[b]</s>bar<e>[/b]</e></B> baz</r>', +					'poll_option_text' => "<r><I><s>[i]</s>foo<e>[/i]</e></I></r>\n<t>bar</t>\n<r><I><s>[i]</s>baz<e>[/i]</e></I></r>", +					'poll_options' => array( +						'<r><I><s>[i]</s>foo<e>[/i]</e></I></r>', +						'<t>bar</t>', +						'<r><I><s>[i]</s>baz<e>[/i]</e></I></r>' +					) +				) +			), +			array( +				array( +					'poll_title' => 'xxx', +					'poll_option_text' => "[quote]quote[/quote]\n:)", +					'poll_max_options'	=> 2, +					'poll_options_size' => 2 +				), +				array( +					'poll_title' => '<t>xxx</t>', +					'poll_option_text' => "<t>[quote]quote[/quote]</t>\n<r><E>:)</E></r>", +					'poll_options' => array( +						'<t>[quote]quote[/quote]</t>', +						'<r><E>:)</E></r>' +					) +				), +				array('You cannot use certain BBCodes: [quote].') +			), +			array( +				array( +					'poll_title' => 'xxx', +					'poll_option_text' => "[flash=12,34]http://example.org/x.swf[/flash]\n:)", +					'poll_max_options'	=> 2, +					'poll_options_size' => 2 +				), +				array( +					'poll_title' => '<t>xxx</t>', +					'poll_option_text' => "<t>[flash=12,34]http://example.org/x.swf[/flash]</t>\n<r><E>:)</E></r>", +					'poll_options' => array( +						'<t>[flash=12,34]http://example.org/x.swf[/flash]</t>', +						'<r><E>:)</E></r>' +					) +				), +				array('You cannot use certain BBCodes: [flash].') +			), +			array( +				array( +					'poll_title' => 'xxx', +					'poll_option_text' => "[b]x\ny[/b]", +					'poll_max_options'	=> 2, +					'poll_options_size' => 2 +				), +				array( +					'poll_title' => '<t>xxx</t>', +					'poll_option_text' => "<r><B><s>[b]</s>x</B></r>\n<t>y[/b]</t>", +					'poll_options' => array( +						'<r><B><s>[b]</s>x</B></r>', +						'<t>y[/b]</t>', +					) +				) +			), +		); +	} + +	/** +	* @dataProvider get_test_cases +	*/ +	public function test_options($original, $expected, array $args, $setup = null, $warn_msg = array()) +	{ +		$this->prepare_s9e_services($setup); + +		$message_parser = new parse_message($original); +		call_user_func_array(array($message_parser, 'parse'), $args); + +		$this->assertSame($expected, $message_parser->message); +		$this->assertSame($warn_msg, $message_parser->warn_msg); +	} + +	public function get_test_cases() +	{ +		return array( +			array( +				'[b]bold[/b]', +				'<r><B><s>[b]</s>bold<e>[/b]</e></B></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				'[b]bold[/b]', +				'<t>[b]bold[/b]</t>', +				array(false, true, true, true, true, true, true) +			), +			array( +				'http://example.org', +				'<r><URL url="http://example.org">http://example.org</URL></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				'http://example.org', +				'<t>http://example.org</t>', +				array(true, false, true, true, true, true, true) +			), +			array( +				':)', +				'<r><E>:)</E></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				':)', +				'<t>:)</t>', +				array(true, true, false, true, true, true, true) +			), +			array( +				'[url=http://example.org][img]http://example.org/img.png[/img][/url]', +				'<r><URL url="http://example.org"><s>[url=http://example.org]</s><IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG><e>[/url]</e></URL></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				'[url=http://example.org][img]http://example.org/img.png[/img][/url]', +				'<r><URL url="http://example.org"><s>[url=http://example.org]</s>[img]http://example.org/img.png[/img]<e>[/url]</e></URL></r>', +				array(true, true, true, false, true, true, true), +				null, +				array('You cannot use certain BBCodes: [img].') +			), +			array( +				'[flash=12,34]http://example.org/foo.swf[/flash]', +				'<r><FLASH height="34" url="http://example.org/foo.swf" width="12"><s>[flash=12,34]</s><URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL><e>[/flash]</e></FLASH></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				'[flash=12,34]http://example.org/foo.swf[/flash]', +				'<r>[flash=12,34]<URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL>[/flash]</r>', +				array(true, true, true, true, false, true, true), +				null, +				array('You cannot use certain BBCodes: [flash].') +			), +			array( +				'[quote="foo"]bar :)[/quote]', +				'<r><QUOTE author="foo"><s>[quote="foo"]</s>bar <E>:)</E><e>[/quote]</e></QUOTE></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				'[quote="foo"]bar :)[/quote]', +				'<r>[quote="foo"]bar <E>:)</E>[/quote]</r>', +				array(true, true, true, true, true, false, true), +				null, +				array('You cannot use certain BBCodes: [quote].') +			), +			array( +				'[url=http://example.org][img]http://example.org/img.png[/img][/url]', +				'<r><URL url="http://example.org"><s>[url=http://example.org]</s><IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG><e>[/url]</e></URL></r>', +				array(true, true, true, true, true, true, true) +			), +			array( +				'[url=http://example.org][img]http://example.org/img.png[/img][/url]', +				'<r>[url=http://example.org]<IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG>[/url]</r>', +				array(true, true, true, true, true, true, false), +				null, +				array('You cannot use certain BBCodes: [url].') +			), +			array( +				'[size=200]200[/size]', +				'<r><SIZE size="200"><s>[size=200]</s>200<e>[/size]</e></SIZE></r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_font_size', 200); +				} +			), +			array( +				'[size=200]200[/size]', +				'<r><SIZE size="200"><s>[size=200]</s>200<e>[/size]</e></SIZE></r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_font_size', 0); +				} +			), +			array( +				'[size=2000]2000[/size]', +				'<t>[size=2000]2000[/size]</t>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_font_size', 200); +				}, +				array('You may only use fonts up to size 200.') +			), +			array( +				'[size=0]0[/size]', +				'<t>[size=0]0[/size]</t>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_font_size', 200); +				} +			), +			array( +				'[size=200]200[/size]', +				'<r><SIZE size="200"><s>[size=200]</s>200<e>[/size]</e></SIZE></r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_sig_font_size', 200); +				} +			), +			array( +				'[size=200]200[/size]', +				'<t>[size=200]200[/size]</t>', +				array(true, true, true, true, true, true, true, true, 'sig'), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_sig_font_size', 120); +				}, +				array('You may only use fonts up to size 120.') +			), +			array( +				'[img]http://example.org/100x100.png[/img]', +				'<r>[img]<URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL>[/img]</r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_height', 12); +				}, +				array('Your images may only be up to 12 pixels high.') +			), +			array( +				'[img]http://example.org/100x100.png[/img]', +				'<r>[img]<URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL>[/img]</r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_width', 34); +				}, +				array('Your images may only be up to 34 pixels wide.') +			), +			array( +				'[img]http://example.org/100x100.png[/img]', +				'<r><IMG src="http://example.org/100x100.png"><s>[img]</s><URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL><e>[/img]</e></IMG></r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_height', 0); +					$phpbb_container->get('config')->set('max_post_img_width', 0); +				} +			), +			array( +				'[img]http://example.org/100x100.png[/img]', +				'<r><IMG src="http://example.org/100x100.png"><s>[img]</s><URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL><e>[/img]</e></IMG></r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_height', 100); +					$phpbb_container->get('config')->set('max_post_img_width', 100); +				} +			), +			array( +				'[img]http://example.org/100x100.png[/img]', +				'<r><IMG src="http://example.org/100x100.png"><s>[img]</s><URL url="http://example.org/100x100.png">http://example.org/100x100.png</URL><e>[/img]</e></IMG></r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_sig_img_height', 12); +					$phpbb_container->get('config')->set('max_sig_img_width', 34); +				} +			), +			array( +				'[img]http://example.org/404.png[/img]', +				'<r>[img]<URL url="http://example.org/404.png">http://example.org/404.png</URL>[/img]</r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_height', 12); +				}, +				array('It was not possible to determine the dimensions of the image.') +			), +			array( +				'[flash=999,999]http://example.org/foo.swf[/flash]', +				'<r>[flash=999,999]<URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL>[/flash]</r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_height', 123); +				}, +				array('Your flash files may only be up to 123 pixels high.') +			), +			array( +				'[flash=999,999]http://example.org/foo.swf[/flash]', +				'<r>[flash=999,999]<URL url="http://example.org/foo.swf">http://example.org/foo.swf</URL>[/flash]</r>', +				array(true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_img_width', 456); +				}, +				array('Your flash files may only be up to 456 pixels wide.') +			), +			array( +				':) :) :)', +				'<r><E>:)</E> <E>:)</E> <E>:)</E></r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_smilies', 3); +				} +			), +			array( +				':) :) :) :)', +				'<r><E>:)</E> <E>:)</E> <E>:)</E> :)</r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_smilies', 3); +				}, +				array('Your message contains too many smilies. The maximum number of smilies allowed is 3.') +			), +			array( +				':) :) :) :)', +				'<r><E>:)</E> <E>:)</E> <E>:)</E> <E>:)</E></r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_smilies', 0); +				} +			), +			array( +				':) :) :) :)', +				'<r><E>:)</E> <E>:)</E> <E>:)</E> <E>:)</E></r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_sig_smilies', 3); +				} +			), +			array( +				':) :) :) :)', +				'<r><E>:)</E> <E>:)</E> <E>:)</E> :)</r>', +				array(true, true, true, true, true, true, true, true, 'sig'), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_sig_smilies', 3); +				}, +				array('Your message contains too many smilies. The maximum number of smilies allowed is 3.') +			), +			array( +				'http://example.org http://example.org http://example.org', +				'<r><URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL> http://example.org</r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_urls', 2); +				}, +				array('Your message contains too many URLs. The maximum number of URLs allowed is 2.') +			), +			array( +				'http://example.org http://example.org http://example.org', +				'<r><URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL></r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_post_urls', 0); +				} +			), +			array( +				'http://example.org http://example.org http://example.org', +				'<r><URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL> <URL url="http://example.org">http://example.org</URL></r>', +				array(true, true, true, true, true, true, true, true), +				function ($phpbb_container) +				{ +					$phpbb_container->get('config')->set('max_sig_urls', 2); +				} +			), +		); +	} +} + +class phpbb_text_processing_message_parser_test_proxy +{ +	protected $response; + +	public function stream_open($url) +	{ +		if (strpos($url, '100x100')) +		{ +			// Return a 100 x 100 PNG image +			$this->response = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQAAAABYmaj5AAAAE0lEQVR4AWOgKxgFo2AUjIJRAAAFeAABHs0ozQAAAABJRU5ErkJggg=='); +		} +		else +		{ +			$this->response = '404 not found'; +		} + +		return true; +	} + +	public function stream_stat() +	{ +		return false; +	} + +	public function stream_read($len) +	{ +		$chunk = substr($this->response, 0, $len); +		$this->response = substr($this->response, $len); + +		return $chunk; +	} + +	public function stream_eof() +	{ +		return ($this->response === false); +	} +} diff --git a/tests/text_processing/smilies_test.php b/tests/text_processing/smilies_test.php new file mode 100644 index 0000000000..3778e5f58c --- /dev/null +++ b/tests/text_processing/smilies_test.php @@ -0,0 +1,49 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_text_processing_smilies_test extends phpbb_test_case +{ +	/** +	* @dataProvider get_text_formatter_tests +	*/ +	public function test_text_formatter($original, $expected) +	{ +		$container = $this->get_test_case_helpers()->set_s9e_services(null, __DIR__ . '/fixtures/smilies.xml'); +		$parser = $container->get('text_formatter.parser'); +		$renderer = $container->get('text_formatter.renderer'); + +		$this->assertSame($expected, $renderer->render($parser->parse($original))); +	} + +	public function get_text_formatter_tests() +	{ +		return array( +			array( +				':) beginning', +				'<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile"> beginning' +			), +			array( +				'end :)', +				'end <img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile">' +			), +			array( +				':)', +				'<img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile">' +			), +			array( +				'xx (18) 8) xx', +				'xx (18) <img class="smilies" src="phpBB/images/smilies/custom.gif" width="17" height="18" alt="8)" title="8)"> xx' +			), +		); +	} +} diff --git a/tests/text_processing/strip_bbcode_test.php b/tests/text_processing/strip_bbcode_test.php new file mode 100644 index 0000000000..9acedc2872 --- /dev/null +++ b/tests/text_processing/strip_bbcode_test.php @@ -0,0 +1,39 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_text_processing_strip_bbcode_test extends phpbb_test_case +{ +	public function test_legacy() +	{ +		$original = '[b:20m4ill1]bold[/b:20m4ill1]'; +		$expected = ' bold '; + +		$actual = $original; +		strip_bbcode($actual); + +		$this->assertSame($expected, $actual, '20m4ill1'); +	} + +	public function test_s9e() +	{ +		$phpbb_container = $this->get_test_case_helpers()->set_s9e_services(); + +		$original = '<r><B><s>[b]</s>bold<e>[/b]</e></B></r>'; +		$expected = ' bold '; + +		$actual = $original; +		strip_bbcode($actual); + +		$this->assertSame($expected, $actual); +	} +} diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.html b/tests/text_processing/tickets_data/PHPBB3-10002.html new file mode 100644 index 0000000000..82990b2253 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10002.html @@ -0,0 +1,2 @@ +<blockquote class="uncited"><div><ul><li>one +<blockquote class="uncited"><div><ul><li>two</li></ul></div></blockquote></li></ul></div></blockquote>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10002.txt b/tests/text_processing/tickets_data/PHPBB3-10002.txt new file mode 100644 index 0000000000..fe2f29073f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10002.txt @@ -0,0 +1,2 @@ +[quote][list][*]one +[quote][list][*]two[/list][/quote]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10122.html b/tests/text_processing/tickets_data/PHPBB3-10122.html new file mode 100644 index 0000000000..f0fb6115b2 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10122.html @@ -0,0 +1 @@ +<ul style="list-style-type: none"><li>This is my indented text</li></ul>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10122.txt b/tests/text_processing/tickets_data/PHPBB3-10122.txt new file mode 100644 index 0000000000..a5e059df66 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10122.txt @@ -0,0 +1 @@ +[list=none][*]This is my indented text[/list]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10268.html b/tests/text_processing/tickets_data/PHPBB3-10268.html new file mode 100644 index 0000000000..c89e63f9a3 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10268.html @@ -0,0 +1,4 @@ +<blockquote><div><cite><a href="http://phpbb.com" class="postlink">http://phpbb.com</a> wrote:</cite>...</div></blockquote> +<blockquote><div><cite><a href="http://phpbb.com" class="postlink"> http://phpbb.com</a> wrote:</cite>...</div></blockquote> +<span style="font-weight: bold"><a href="http://phpbb.com" class="postlink">http://phpbb.com</a></span><br> +<span style="font-weight: bold"> <a href="http://phpbb.com" class="postlink">http://phpbb.com</a></span><br> diff --git a/tests/text_processing/tickets_data/PHPBB3-10268.txt b/tests/text_processing/tickets_data/PHPBB3-10268.txt new file mode 100644 index 0000000000..b4e49c9454 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10268.txt @@ -0,0 +1,4 @@ +[quote="http://phpbb.com"]...[/quote] +[quote=" http://phpbb.com"]...[/quote] +[b]http://phpbb.com[/b] +[b] http://phpbb.com[/b] diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.html b/tests/text_processing/tickets_data/PHPBB3-10425.html new file mode 100644 index 0000000000..522b2f8858 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10425.html @@ -0,0 +1,3 @@ +<a href="http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" class="postlink">http://ar.wikipedia.org/wiki/الصفحة_الرئيسية</a><br> +<a href="http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" class="postlink">http://ar.wikipedia.org/wiki/الصفحة_الرئيسية</a><br> +<a href="http://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" class="postlink">link</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10425.txt b/tests/text_processing/tickets_data/PHPBB3-10425.txt new file mode 100644 index 0000000000..d93c0446b6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10425.txt @@ -0,0 +1,3 @@ +http://ar.wikipedia.org/wiki/الصفحة_الرئيسية +[url]http://ar.wikipedia.org/wiki/الصفحة_الرئيسية[/url] +[url=http://ar.wikipedia.org/wiki/الصفحة_الرئيسية]link[/url]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.html b/tests/text_processing/tickets_data/PHPBB3-10587.html new file mode 100644 index 0000000000..4c2e536989 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10587.html @@ -0,0 +1,2 @@ +<a href="http://example.org/?tourney%5Bid%5D=34&action=brackets" class="postlink">http://example.org/?tourney[id]=34&action=brackets</a><br> +<a href="http://example.org/?tourney%5Bid%5D=34&action=brackets" class="postlink">link</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10587.txt b/tests/text_processing/tickets_data/PHPBB3-10587.txt new file mode 100644 index 0000000000..84788b720d --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10587.txt @@ -0,0 +1,2 @@ +[url]http://example.org/?tourney[id]=34&action=brackets[/url] +[url="http://example.org/?tourney[id]=34&action=brackets"]link[/url]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.html b/tests/text_processing/tickets_data/PHPBB3-10922.html new file mode 100644 index 0000000000..3ff117f171 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10922.html @@ -0,0 +1,9 @@ +<a href="mailto:user@example.org">user@example.org</a><br> +<a href="mailto:user@example.org">...</a><br> +<a href="mailto:user@example.org">...</a><br> +<a href="mailto:user@example.org?subject=Hello">...</a><br> +<a href="mailto:user@example.org?subject=Hi%20there">user@example.org</a><br> +<a href="mailto:user@example.org?body=Hi%20there">user@example.org</a><br> +<a href="mailto:user@example.org?subject=Hello&body=Sent%20from%20phpBB">user@example.org</a><br> +<a href="mailto:user@example.org?subject=Hello&body=Sent%20from%20phpBB">user@example.org</a><br> +<a href="mailto:user@example.org?subject=Hello&body=Sent%20from%20phpBB">...</a><br> diff --git a/tests/text_processing/tickets_data/PHPBB3-10922.txt b/tests/text_processing/tickets_data/PHPBB3-10922.txt new file mode 100644 index 0000000000..e533ce6ed5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10922.txt @@ -0,0 +1,9 @@ +[email]user@example.org[/email] +[email=user@example.org]...[/email] +[email=user@example.org ]...[/email] +[email=user@example.org subject="Hello"]...[/email] +[email subject="Hi there"]user@example.org[/email] +[email body="Hi there"]user@example.org[/email] +[email subject="Hello" body="Sent from phpBB"]user@example.org[/email] +[email body="Sent from phpBB" subject="Hello"]user@example.org[/email] +[email body="Sent from phpBB" subject="Hello" email="user@example.org"]...[/email] diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.html b/tests/text_processing/tickets_data/PHPBB3-10989.html new file mode 100644 index 0000000000..cd24df60e5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10989.html @@ -0,0 +1,8 @@ +<blockquote><div><cite>Lorem wrote:</cite>[quote="Lorem"<blockquote class="uncited"><div> Suspendisse iaculis porta tempor. Nulla.</div></blockquote> + Nullam a tortor sit amet.</div></blockquote> + Proin ac mi eget magna.<br> + +<blockquote><div><cite>Lorem wrote:</cite>Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.</div></blockquote> + +<br> +Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper.
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-10989.txt b/tests/text_processing/tickets_data/PHPBB3-10989.txt new file mode 100644 index 0000000000..dc2430f210 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-10989.txt @@ -0,0 +1,8 @@ +[quote="Lorem"][quote="Lorem"[quote] Suspendisse iaculis porta tempor. Nulla.[/quote] + Nullam a tortor sit amet.[/quote] + Proin ac mi eget magna. + +[quote="Lorem"]Quisque fermentum tortor quis odio scelerisque consequat fermentum urna gravida. In semper vehicula condimentum. Donec suscipit ante imperdiet augue rhoncus.[/quote] + + +Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Maecenas quis odio orci, sit amet semper.
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.html b/tests/text_processing/tickets_data/PHPBB3-11153.html new file mode 100644 index 0000000000..0f67ac4bc0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.html @@ -0,0 +1 @@ +<a href="mailto:user@example.org">...</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.txt b/tests/text_processing/tickets_data/PHPBB3-11153.txt new file mode 100644 index 0000000000..d2794978d9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.txt @@ -0,0 +1 @@ +[myemail=user@example.org]...[/myemail]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11153.xml b/tests/text_processing/tickets_data/PHPBB3-11153.xml new file mode 100644 index 0000000000..a7fc69520b --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11153.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>myemail</value> +			<value></value> +			<value>1</value> +			<value>[myemail={EMAIL}]{TEXT}[/myemail]</value> +			<value><![CDATA[<a href="mailto:{EMAIL}">{TEXT}</a>]]></value> +			<value><![CDATA[!\[myemail\=(([\w\!\#$\%\&'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?))\](.*?)\[/myemail\]!ies]]></value> +			<value><![CDATA['[myemail='.$this->bbcode_specialchars('${1}').':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/myemail:$uid]']]></value> +			<value><![CDATA[!\[myemail\=(([\w\!\#$\%\&'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)):$uid\](.*?)\[/myemail:$uid\]!s]]></value> +			<value><![CDATA[<a href="mailto:${1}">${2}</a>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-11742.html b/tests/text_processing/tickets_data/PHPBB3-11742.html new file mode 100644 index 0000000000..e7890eef19 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11742.html @@ -0,0 +1 @@ +<div class="codebox"><p>CODE: <a href="#" onclick="selectCode(this); return false;">Select all</a></p><pre><code>	tab</code></pre></div>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-11742.txt b/tests/text_processing/tickets_data/PHPBB3-11742.txt new file mode 100644 index 0000000000..db72e5dda0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-11742.txt @@ -0,0 +1 @@ +[code]	tab[/code]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.html b/tests/text_processing/tickets_data/PHPBB3-12195.html new file mode 100644 index 0000000000..c286c0fee9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12195.html @@ -0,0 +1 @@ +<a href="//example.org/" class="postlink"><img src="//example.org/img.png" class="postimage" alt="Image"></a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-12195.txt b/tests/text_processing/tickets_data/PHPBB3-12195.txt new file mode 100644 index 0000000000..b66dbd5d96 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12195.txt @@ -0,0 +1 @@ +[url=//example.org/][img]//example.org/img.png[/img][/url]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-12221.html b/tests/text_processing/tickets_data/PHPBB3-12221.html new file mode 100644 index 0000000000..567f552e84 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12221.html @@ -0,0 +1 @@ +<a href="https://example.com/test/#?javascript:lolhax" class="postlink">https://example.com/test/#?javascript:lolhax</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-12221.txt b/tests/text_processing/tickets_data/PHPBB3-12221.txt new file mode 100644 index 0000000000..01a0bf8667 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-12221.txt @@ -0,0 +1 @@ +https://example.com/test/#?javascript:lolhax
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.html b/tests/text_processing/tickets_data/PHPBB3-13425.html new file mode 100644 index 0000000000..a3b6d21f40 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13425.html @@ -0,0 +1 @@ +<blockquote class="uncited"><div><img class="smilies" src="phpBB/images/smilies/icon_lol.gif" width="15" height="17" alt=":lol:" title="Laughing"> starts with a smiley</div></blockquote>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.txt b/tests/text_processing/tickets_data/PHPBB3-13425.txt new file mode 100644 index 0000000000..8456410df5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13425.txt @@ -0,0 +1 @@ +[quote]:lol: starts with a smiley[/quote]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13425.xml b/tests/text_processing/tickets_data/PHPBB3-13425.xml new file mode 100644 index 0000000000..cbdcaa7fb7 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13425.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>22</value> +			<value>:lol:</value> +			<value>Laughing</value> +			<value>icon_lol.gif</value> +			<value>15</value> +			<value>17</value> +			<value>22</value> +			<value>1</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-13451.html b/tests/text_processing/tickets_data/PHPBB3-13451.html new file mode 100644 index 0000000000..e0892c18a9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13451.html @@ -0,0 +1 @@ +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@example.org
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13451.txt b/tests/text_processing/tickets_data/PHPBB3-13451.txt new file mode 100644 index 0000000000..e0892c18a9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13451.txt @@ -0,0 +1 @@ +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@example.org
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.html b/tests/text_processing/tickets_data/PHPBB3-13641.html new file mode 100644 index 0000000000..1bd1c06dbb --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13641.html @@ -0,0 +1 @@ +<code>[color=#FF0000]</code> - <span style="color: #FF0000">red</span>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.txt b/tests/text_processing/tickets_data/PHPBB3-13641.txt new file mode 100644 index 0000000000..58f324715e --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13641.txt @@ -0,0 +1 @@ +[c][color=#FF0000][/c] - [color=#FF0000]red[/color]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13641.xml b/tests/text_processing/tickets_data/PHPBB3-13641.xml new file mode 100644 index 0000000000..451c5c69cd --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13641.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>c</value> +			<value></value> +			<value>1</value> +			<value>[c]{TEXT}[/c]</value> +			<value><![CDATA[<code>{TEXT}</code>]]></value> +			<value><\[/c\]!ies]]></value> +			<value><![CDATA['[c:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'[/c:$uid]']]></value> +			<value><\[/c:$uid\]!s]]></value> +			<value><![CDATA[<code>${1}</code>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.html b/tests/text_processing/tickets_data/PHPBB3-13921.html new file mode 100644 index 0000000000..6a9dc7f504 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13921.html @@ -0,0 +1 @@ +<span style="font-size: 200%; line-height: normal"></span><div style="text-align:center"><span style="font-size: 200%; line-height: normal">xxx</span></div>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.txt b/tests/text_processing/tickets_data/PHPBB3-13921.txt new file mode 100644 index 0000000000..392da0c3c8 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13921.txt @@ -0,0 +1 @@ +[size=200][center]xxx[/center][/size]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-13921.xml b/tests/text_processing/tickets_data/PHPBB3-13921.xml new file mode 100644 index 0000000000..8d39246bb4 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-13921.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>center</value> +			<value></value> +			<value>1</value> +			<value>[center]{TEXT}[/center]</value> +			<value><![CDATA[<div style="text-align:center">{TEXT}</div>]]></value> +			<value>!\[center\](.*?)\[/center\]!ies</value> +			<value>'[center:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'[/center:$uid]'</value> +			<value>!\[center:$uid\](.*?)\[/center:$uid\]!s</value> +			<value><![CDATA[<div style="text-align:center">${1}</div>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-14260.html b/tests/text_processing/tickets_data/PHPBB3-14260.html new file mode 100644 index 0000000000..c7e7cad237 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14260.html @@ -0,0 +1 @@ +<a href="http://example.org/article/S0883-9441%2811%290483-7/pdf" class="postlink">http://example.org/article/S0883-9441(11)0483-7/pdf</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14260.txt b/tests/text_processing/tickets_data/PHPBB3-14260.txt new file mode 100644 index 0000000000..f95523c00e --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14260.txt @@ -0,0 +1 @@ +http://example.org/article/S0883-9441(11)0483-7/pdf
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14405.html b/tests/text_processing/tickets_data/PHPBB3-14405.html new file mode 100644 index 0000000000..5e76e032ec --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14405.html @@ -0,0 +1 @@ +[url=<a href="http://example.org" class="postlink">http://example.org</a>]...
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14405.txt b/tests/text_processing/tickets_data/PHPBB3-14405.txt new file mode 100644 index 0000000000..7005b36b23 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14405.txt @@ -0,0 +1 @@ +[url=http://example.org]...
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14663.html b/tests/text_processing/tickets_data/PHPBB3-14663.html new file mode 100644 index 0000000000..b18bcfd52b --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14663.html @@ -0,0 +1 @@ +<input type="button" value="Кнопка!"> Тест
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14663.txt b/tests/text_processing/tickets_data/PHPBB3-14663.txt new file mode 100644 index 0000000000..5443ae3046 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14663.txt @@ -0,0 +1 @@ +[test]Тест[/test]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14663.xml b/tests/text_processing/tickets_data/PHPBB3-14663.xml new file mode 100644 index 0000000000..423d01e242 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14663.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>test</value> +			<value></value> +			<value>1</value> +			<value>[test]{TEXT}[/test]</value> +			<value><![CDATA[<input type=button value="Кнопка!" /> {TEXT}]]></value> +			<value><\[/test\]!ies]]></value> +			<value><![CDATA['[test:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'[/test:$uid]']]></value> +			<value><\[/test:$uid\]!s]]></value> +			<value><![CDATA[<input type=button value="Кнопка!" /> ${1}]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-14706.html b/tests/text_processing/tickets_data/PHPBB3-14706.html new file mode 100644 index 0000000000..b8f74c9e93 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14706.html @@ -0,0 +1 @@ +<ul><li><ol style="list-style-type: lower-alpha"><li>a</li><li>b</li><li>c</li><li>d</li><li>e</li></ol></li><li>outer</li></ul>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14706.txt b/tests/text_processing/tickets_data/PHPBB3-14706.txt new file mode 100644 index 0000000000..8ec2e9cd35 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14706.txt @@ -0,0 +1 @@ +[list][list=a][*]a[*]b[*]c[*]d[*]e[/list][*]outer[/list]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14740.html b/tests/text_processing/tickets_data/PHPBB3-14740.html new file mode 100644 index 0000000000..a1986a0901 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14740.html @@ -0,0 +1,2 @@ +<div id="modremark"><div id="modremarkexclamation">!</div><div><div id="moderemarktitle">Moderatoropmerking from: neufke</div><div id="moderemarktext">Mod Remark</div></div></div> +<div id="modremark"><div id="modremarkexclamation">!</div><div><div id="moderemarktitle">Moderatoropmerking from: neufke</div><div id="moderemarktext">Mod Remark</div></div></div>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14740.txt b/tests/text_processing/tickets_data/PHPBB3-14740.txt new file mode 100644 index 0000000000..c5b2e74513 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14740.txt @@ -0,0 +1,2 @@ +[mod=neufke]Mod Remark[/mod] +[mod="neufke"]Mod Remark[/mod]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14740.xml b/tests/text_processing/tickets_data/PHPBB3-14740.xml new file mode 100644 index 0000000000..9e7dc9760c --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14740.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>mod=</value> +			<value></value> +			<value>1</value> +			<value>[mod="{TEXT1}"]{TEXT2}[/mod]</value> +			<value><![CDATA[<div id="modremark"> +	<div id="modremarkexclamation">!</div> +	<div> +		<div id="moderemarktitle">Moderatoropmerking {L_FROM}{L_COLON} {TEXT1}</div> +		<div id="moderemarktext">{TEXT2}</div> +	</div> +</div>]]></value> +			<value>!\[mod\="(.*?)"\](.*?)\[/mod\]!ies</value> +			<value>'[mod="'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'":$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/mod:$uid]'</value> +			<value>!\[mod\="(.*?)":$uid\](.*?)\[/mod:$uid\]!s</value> +			<value><![CDATA[<div id="modremark"> +	<div id="modremarkexclamation">!</div> +	<div> +		<div id="moderemarktitle">Moderatoropmerking {L_FROM}{L_COLON} ${1}</div> +		<div id="moderemarktext">${2}</div> +	</div> +</div>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-14846.html b/tests/text_processing/tickets_data/PHPBB3-14846.html new file mode 100644 index 0000000000..461ca25bc6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14846.html @@ -0,0 +1 @@ +<div style="padding: .2em .5em; font-size: .8em; width: 200px; background: #FFD;">moderator text<div style="font-weight: bold; text-align: right">- Mickroz</div></div>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14846.txt b/tests/text_processing/tickets_data/PHPBB3-14846.txt new file mode 100644 index 0000000000..ded7b3f1fe --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14846.txt @@ -0,0 +1 @@ +[mod=Mickroz]moderator text[/mod]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-14846.xml b/tests/text_processing/tickets_data/PHPBB3-14846.xml new file mode 100644 index 0000000000..94b094f0e3 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-14846.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>mod=</value> +			<value></value> +			<value>1</value> +			<value>[mod={TEXT1}]{TEXT2}[/mod]</value> +			<value><![CDATA[<div style="padding: .2em .5em; font-size: .8em; width: 200px; background: #FFD;">{TEXT2}<div style="font-weight: bold; text-align: right">- {TEXT1}</div></div>]]></value> +			<value><\[/mod\]!ies]]></value> +			<value><![CDATA['[mod='.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).':$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${2}')).'[/mod:$uid]']]></value> +			<value><\[/mod:$uid\]!s]]></value> +			<value><![CDATA[<div style="padding: .2em .5em; font-size: .8em; width: 200px; background: #FFD;">${2}<div style="font-weight: bold; text-align: right">- ${1}</div></div>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.before.php b/tests/text_processing/tickets_data/PHPBB3-3981.before.php new file mode 100644 index 0000000000..1c326b52af --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.before.php @@ -0,0 +1,21 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +function before_assert_phpbb3_3981($vars) +{ +	if (!function_exists('idn_to_ascii')) +	{ +		extract($vars); +		$test->markTestSkipped('International URLs need idn_to_ascii()'); +	} +} diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.html b/tests/text_processing/tickets_data/PHPBB3-3981.html new file mode 100644 index 0000000000..e5f1b4561d --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.html @@ -0,0 +1 @@ +<a href="http://www.xn--ndaaa.com" class="postlink">http://www.ööö.com</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-3981.txt b/tests/text_processing/tickets_data/PHPBB3-3981.txt new file mode 100644 index 0000000000..976823f1d1 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-3981.txt @@ -0,0 +1 @@ +[url]http://www.ööö.com[/url]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.html b/tests/text_processing/tickets_data/PHPBB3-7187.html new file mode 100644 index 0000000000..a37cdf038e --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.html @@ -0,0 +1 @@ +<blockquote class="uncited"><div><img class="smilies" src="phpBB/images/smilies/icon_e_geek.gif" width="17" height="17" alt=":geek:" title="Geek"> <img class="smilies" src="phpBB/images/smilies/icon_e_ugeek.gif" width="17" height="18" alt=":ugeek:" title="Uber Geek"></div></blockquote>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.txt b/tests/text_processing/tickets_data/PHPBB3-7187.txt new file mode 100644 index 0000000000..584151a083 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.txt @@ -0,0 +1 @@ +[quote]:geek: :ugeek:[/quote]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7187.xml b/tests/text_processing/tickets_data/PHPBB3-7187.xml new file mode 100644 index 0000000000..d270b12619 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7187.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>41</value> +			<value>:geek:</value> +			<value>Geek</value> +			<value>icon_e_geek.gif</value> +			<value>17</value> +			<value>17</value> +			<value>41</value> +			<value>1</value> +		</row> +		<row> +			<value>42</value> +			<value>:ugeek:</value> +			<value>Uber Geek</value> +			<value>icon_e_ugeek.gif</value> +			<value>17</value> +			<value>18</value> +			<value>42</value> +			<value>1</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.after.php b/tests/text_processing/tickets_data/PHPBB3-7275.after.php new file mode 100644 index 0000000000..99f41d7839 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.after.php @@ -0,0 +1,19 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +function after_assert_phpbb3_7275($vars) +{ +	extract($vars); +	decode_message($parsed_text); +	$test->assertSame($original, $parsed_text); +} diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.html b/tests/text_processing/tickets_data/PHPBB3-7275.html new file mode 100644 index 0000000000..470aebb5d0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.html @@ -0,0 +1 @@ +<div align="center"><img class="smilies" src="phpBB/images/smilies/icon_e_smile.gif" width="15" height="17" alt=":)" title="Smile"></div>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.txt b/tests/text_processing/tickets_data/PHPBB3-7275.txt new file mode 100644 index 0000000000..8de97d67e0 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.txt @@ -0,0 +1 @@ +[center]:)[/center]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-7275.xml b/tests/text_processing/tickets_data/PHPBB3-7275.xml new file mode 100644 index 0000000000..9e979afffb --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-7275.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>center</value> +			<value></value> +			<value>1</value> +			<value>[center]{TEXT}[/center]</value> +			<value><![CDATA[<div align="center">{TEXT}</div>]]></value> +			<value>!\[center\](.*?)\[/center\]!ies</value> +			<value><![CDATA['[center:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'[/center:$uid]']]></value> +			<value>!\[center:$uid\](.*?)\[/center:$uid\]!s</value> +			<value><![CDATA[<div align="center">${1}</div>]]></value> +		</row> +	</table> + +	<table name="phpbb_smilies"> +		<column>smiley_id</column> +		<column>code</column> +		<column>emotion</column> +		<column>smiley_url</column> +		<column>smiley_width</column> +		<column>smiley_height</column> +		<column>smiley_order</column> +		<column>display_on_posting</column> +		<row> +			<value>4</value> +			<value>:)</value> +			<value>Smile</value> +			<value>icon_e_smile.gif</value> +			<value>15</value> +			<value>17</value> +			<value>4</value> +			<value>1</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.html b/tests/text_processing/tickets_data/PHPBB3-8419.html new file mode 100644 index 0000000000..38df626a94 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-8419.html @@ -0,0 +1 @@ +<span style="font-style: italic"><span style="font-weight: bold"><span style="color: #FF0000">tę </span></span></span>przykład
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.txt b/tests/text_processing/tickets_data/PHPBB3-8419.txt new file mode 100644 index 0000000000..dac47823b6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-8419.txt @@ -0,0 +1 @@ +[ort]tę [/ort]przykład
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-8419.xml b/tests/text_processing/tickets_data/PHPBB3-8419.xml new file mode 100644 index 0000000000..2f1df345f9 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-8419.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>myemail</value> +			<value></value> +			<value>1</value> +			<value>[ort]{TEXT}[/ort]</value> +			<value><![CDATA[<span style="font-style: italic"><span style="font-weight: bold"><span style="color: #FF0000">{TEXT}</span></span></span>]]></value> +			<value><\[/ort\]!ies]]></value> +			<value><![CDATA['[ort:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', ''', '(', ')'), trim('${1}')).'[/ort:$uid]']]></value> +			<value><\[/ort:$uid\]!s]]></value> +			<value><![CDATA[<span style="font-style: italic"><span style="font-weight: bold"><span style="color: #FF0000">${1}</span></span></span>]]></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.html b/tests/text_processing/tickets_data/PHPBB3-9073.html new file mode 100644 index 0000000000..ff1f9fd0ce --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9073.html @@ -0,0 +1,2 @@ +<a href="http://www.xxxx-xx-xxxx.com/" class="postlink">http://www.xxxx-xx-xxxx.com/</a><br> +<a href="http://www.xxxx-xx-xxxx.com/" class="postlink">http://www.xxxx-xx-xxxx.com/</a><br> diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.txt b/tests/text_processing/tickets_data/PHPBB3-9073.txt new file mode 100644 index 0000000000..2c271173ce --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9073.txt @@ -0,0 +1,2 @@ +http://www.some-ad-site.com/ +[url]http://www.some-ad-site.com/[/url] diff --git a/tests/text_processing/tickets_data/PHPBB3-9073.xml b/tests/text_processing/tickets_data/PHPBB3-9073.xml new file mode 100644 index 0000000000..d635d51ed1 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9073.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_words"> +		<column>word_id</column> +		<column>word</column> +		<column>replacement</column> + +		<row> +			<value>1</value> +			<value>http://www.some-ad-site.com*</value> +			<value>http://www.xxxx-xx-xxxx.com</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.html b/tests/text_processing/tickets_data/PHPBB3-9377.html new file mode 100644 index 0000000000..dcfb79c173 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.html @@ -0,0 +1 @@ +<span style="color:red">red <span style="color:blue">blue</span> red</span>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.txt b/tests/text_processing/tickets_data/PHPBB3-9377.txt new file mode 100644 index 0000000000..dfd71492c5 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.txt @@ -0,0 +1 @@ +[red]red [blue]blue[/blue] red[/red]
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9377.xml b/tests/text_processing/tickets_data/PHPBB3-9377.xml new file mode 100644 index 0000000000..1d8ee3d53f --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9377.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_bbcodes"> +		<column>bbcode_id</column> +		<column>bbcode_tag</column> +		<column>bbcode_helpline</column> +		<column>display_on_posting</column> +		<column>bbcode_match</column> +		<column>bbcode_tpl</column> +		<column>first_pass_match</column> +		<column>first_pass_replace</column> +		<column>second_pass_match</column> +		<column>second_pass_replace</column> + +		<row> +			<value>13</value> +			<value>red</value> +			<value></value> +			<value>1</value> +			<value>[red]{TEXT}[/red]</value> +			<value><span style="color:red">{TEXT}</span></value> +			<value>!\[red\](.*?)\[/red\]!ies</value> +			<value>'[red:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/red:$uid]'</value> +			<value>!\[red:$uid\](.*?)\[/red:$uid\]!s</value> +			<value><span style="color:red">${1}</span></value> +		</row> + +		<row> +			<value>14</value> +			<value>blue</value> +			<value></value> +			<value>1</value> +			<value>[blue]{TEXT}[/blue]</value> +			<value><span style="color:blue">{TEXT}</span></value> +			<value>!\[blue\](.*?)\[/blue\]!ies</value> +			<value>'[blue:$uid]'.str_replace(array("\r\n", '\"', '\'', '(', ')'), array("\n", '"', '&#39;', '&#40;', '&#41;'), trim('${1}')).'[/blue:$uid]'</value> +			<value>!\[blue:$uid\](.*?)\[/blue:$uid\]!s</value> +			<value><span style="color:blue">${1}</span></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_processing/tickets_data/PHPBB3-9791.html b/tests/text_processing/tickets_data/PHPBB3-9791.html new file mode 100644 index 0000000000..3d0108c8a6 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9791.html @@ -0,0 +1 @@ +<a href="http://www.phpbb.com/community/search.php?keywords=bogus&terms=all&author=&fid%5B%5D=46&sc=1&sf=all&sr=posts&sk=t&sd=d&st=0&ch=300&t=0&submit=Search" class="postlink">http://www.phpbb.com/community/search.p ... mit=Search</a>
\ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-9791.txt b/tests/text_processing/tickets_data/PHPBB3-9791.txt new file mode 100644 index 0000000000..e29b20086d --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-9791.txt @@ -0,0 +1 @@ +http://www.phpbb.com/community/search.php?keywords=bogus&terms=all&author=&fid[]=46&sc=1&sf=all&sr=posts&sk=t&sd=d&st=0&ch=300&t=0&submit=Search
\ No newline at end of file diff --git a/tests/text_processing/tickets_test.php b/tests/text_processing/tickets_test.php new file mode 100644 index 0000000000..6230191a69 --- /dev/null +++ b/tests/text_processing/tickets_test.php @@ -0,0 +1,90 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class phpbb_text_processing_tickets_test extends phpbb_test_case +{ +	/** +	* @dataProvider get_tickets_data +	*/ +	public function test_tickets($ticket_id, $original, $expected, $fixture, $before_assert, $after_assert) +	{ +		global $phpbb_container; + +		$phpbb_container = new phpbb_mock_container_builder; + +		$this->get_test_case_helpers()->set_s9e_services($phpbb_container, $fixture); + +		$parser   = $phpbb_container->get('text_formatter.parser'); +		$renderer = $phpbb_container->get('text_formatter.renderer'); + +		if (isset($before_assert)) +		{ +			$test = $this; +			$before_assert(get_defined_vars()); +		} + +		$parsed_text = $parser->parse($original); + +		$this->assertSame($expected, $renderer->render($parsed_text)); + +		if (isset($after_assert)) +		{ +			$test = $this; +			$after_assert(get_defined_vars()); +		} +	} + +	public function get_tickets_data() +	{ +		$tests = array(); + +		foreach (glob(__DIR__ . '/tickets_data/*.txt') as $txt_filename) +		{ +			$ticket_id     = basename($txt_filename, '.txt'); +			$html_filename = substr($txt_filename, 0, -3) . 'html'; +			$xml_filename  = substr($txt_filename, 0, -3) . 'xml'; +			$before_filename = substr($txt_filename, 0, -3) . 'before.php'; +			$after_filename  = substr($txt_filename, 0, -3) . 'after.php'; + +			if (!file_exists($xml_filename)) +			{ +				$xml_filename = __DIR__ . '/../fixtures/empty.xml'; +			} + +			$before_assert = null; +			if (file_exists($before_filename)) +			{ +				include($before_filename); +				$before_assert = 'before_assert_' . strtolower(str_replace('-', '_', $ticket_id)); +			} + +			$after_assert = null; +			if (file_exists($after_filename)) +			{ +				include($after_filename); +				$after_assert = 'after_assert_' . strtolower(str_replace('-', '_', $ticket_id)); +			} + +			$tests[] = array( +				$ticket_id, +				file_get_contents($txt_filename), +				file_get_contents($html_filename), +				$xml_filename, +				$before_assert, +				$after_assert +			); +		} + +		return $tests; +	} +} diff --git a/tests/text_reparser/base_test.php b/tests/text_reparser/base_test.php new file mode 100644 index 0000000000..af2d56ea51 --- /dev/null +++ b/tests/text_reparser/base_test.php @@ -0,0 +1,69 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; + +class phpbb_textreparser_base_test extends phpbb_database_test_case +{ +	protected $db; + +	public function setUp() +	{ +		global $config; +		if (!isset($config)) +		{ +			$config = new \phpbb\config\config(array()); +		} +		$this->get_test_case_helpers()->set_s9e_services(); +		$this->db = $this->new_dbal(); +		parent::setUp(); +	} + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/base.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\post_text($this->db, POSTS_TABLE); +	} + +	protected function get_rows(array $ids) +	{ +		$sql = 'SELECT post_id AS id, post_text AS text +			FROM ' . POSTS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('post_id', $ids) . ' +			ORDER BY id'; +		$result = $this->db->sql_query($sql); +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); + +		return $rows; +	} + +	public function test_reparse_empty() +	{ +		$this->get_reparser()->reparse_range(1, 1); + +		$this->assertEquals( +			array( +				array( +					'id'   => 1, +					'text' => '<t></t>' +				) +			), +			$this->get_rows(array(1)) +		); +	} +} diff --git a/tests/text_reparser/fixtures/base.xml b/tests/text_reparser/fixtures/base.xml new file mode 100644 index 0000000000..a4921a8823 --- /dev/null +++ b/tests/text_reparser/fixtures/base.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_posts"> +		<column>post_id</column> +		<column>enable_bbcode</column> +		<column>enable_smilies</column> +		<column>enable_magic_url</column> +		<column>post_text</column> +		<column>bbcode_uid</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value></value> +			<value>abcd1234</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/fixtures/config_text.xml b/tests/text_reparser/fixtures/config_text.xml new file mode 100644 index 0000000000..ba8e1fcfcc --- /dev/null +++ b/tests/text_reparser/fixtures/config_text.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_config_text"> +		<column>config_name</column> +		<column>config_value</column> +	</table> +</dataset> diff --git a/tests/text_reparser/manager_test.php b/tests/text_reparser/manager_test.php new file mode 100644 index 0000000000..df6adacb66 --- /dev/null +++ b/tests/text_reparser/manager_test.php @@ -0,0 +1,117 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +require_once __DIR__ . '/../mock/container_builder.php'; +require_once __DIR__ . '/../test_framework/phpbb_database_test_case.php'; + +class phpbb_text_reparser_manager_test extends phpbb_database_test_case +{ +	/** @var \phpbb\config\config */ +	protected $config; + +	/** @var \phpbb\config\db_text */ +	protected $config_text; + +	/** @var \phpbb\textreparser\manager */ +	protected $reparser_manager; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/config_text.xml'); +	} + +	public function setUp() +	{ +		parent::setUp(); + +		$this->config = new \phpbb\config\config(array( +			'test_reparser_cron_interval'	=> 0, +			'my_reparser_cron_interval'		=> 100, +		)); + +		$db = $this->new_dbal(); +		$this->config_text = new \phpbb\config\db_text($db, 'phpbb_config_text'); + +		$service_collection = new \phpbb\di\service_collection(new phpbb_mock_container_builder()); +		$service_collection->add('test_reparser'); +		$service_collection->add('another_reparser'); +		$service_collection->add('my_reparser'); + +		$this->reparser_manager = new \phpbb\textreparser\manager($this->config, $this->config_text, $service_collection); +	} + +	public function test_get_resume_data() +	{ +		$resume_data = array( +			'test_reparser'	=> array( +				'range-min'		=> 0, +				'range-max'		=> 100, +				'range-size'	=> 50, +			), +		); +		$this->config_text->set('reparser_resume', serialize($resume_data)); + +		$this->assert_array_content_equals($resume_data['test_reparser'], $this->reparser_manager->get_resume_data('test_reparser')); +		$this->assertEmpty($this->reparser_manager->get_resume_data('another_reparser')); +	} + +	public function test_update_resume_data() +	{ +		$resume_data = array( +			'test_reparser'	=> array( +				'range-min'		=> 0, +				'range-max'		=> 100, +				'range-size'	=> 50, +			), +		); +		$this->config_text->set('reparser_resume', serialize($resume_data)); + +		$this->reparser_manager->update_resume_data('another_reparser', 5, 20, 10, false); +		$this->assert_array_content_equals($resume_data, unserialize($this->config_text->get('reparser_resume'))); + +		$this->reparser_manager->update_resume_data('test_reparser', 0, 50, 50); +		$resume_data = array( +			'test_reparser'	=> array( +				'range-min'		=> 0, +				'range-max'		=> 50, +				'range-size'	=> 50, +			), +			'another_reparser'	=> array( +				'range-min'		=> 5, +				'range-max'		=> 20, +				'range-size'	=> 10, +			), +		); +		$this->assert_array_content_equals($resume_data, unserialize($this->config_text->get('reparser_resume'))); +	} + +	public function test_schedule() +	{ +		$this->reparser_manager->schedule('no_reparser', 21); +		$this->assertArrayNotHasKey('no_reparser_cron_interval', $this->config); + +		$this->reparser_manager->schedule('another_reparser', 42); +		$this->assertArrayNotHasKey('another_reparser_cron_interval', $this->config); + +		$this->reparser_manager->schedule('test_reparser', 20); +		$this->assertEquals(20, $this->config['test_reparser_cron_interval']); +	} + +	public function test_schedule_all() +	{ +		$this->reparser_manager->schedule_all(180); +		$this->assertEquals(180, $this->config['test_reparser_cron_interval']); +		$this->assertEquals(180, $this->config['my_reparser_cron_interval']); +		$this->assertArrayNotHasKey('another_reparser_cron_interval', $this->config); +	} +} diff --git a/tests/text_reparser/plugins/contact_admin_info_test.php b/tests/text_reparser/plugins/contact_admin_info_test.php new file mode 100644 index 0000000000..757b02be39 --- /dev/null +++ b/tests/text_reparser/plugins/contact_admin_info_test.php @@ -0,0 +1,95 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; + +class phpbb_textreparser_contact_admin_info_test extends phpbb_database_test_case +{ +	protected $db; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/contact_admin_info.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\contact_admin_info(new \phpbb\config\db_text($this->db, CONFIG_TEXT_TABLE)); +	} + +	protected function get_rows() +	{ +		$sql = 'SELECT config_name, config_value +			FROM ' . CONFIG_TEXT_TABLE . ' +			ORDER BY config_name'; +		$result = $this->db->sql_query($sql); +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); + +		return $rows; +	} + +	public function setUp() +	{ +		global $config; +		if (!isset($config)) +		{ +			$config = new \phpbb\config\config(array()); +		} +		$this->get_test_case_helpers()->set_s9e_services(); +		$this->db = $this->new_dbal(); +		parent::setUp(); +	} + +	public function test_get_max_id() +	{ +		$reparser = $this->get_reparser(); +		$this->assertEquals(1, $reparser->get_max_id()); +	} + +	public function test_dry_run() +	{ +		$old_rows = $this->get_rows(); +		$reparser = $this->get_reparser(); +		$reparser->disable_save(); +		$reparser->reparse_range(1, 1); +		$new_rows = $this->get_rows(); +		$this->assertEquals($old_rows, $new_rows); +	} + +	public function test_reparse() +	{ +		$reparser = $this->get_reparser(); +		$reparser->enable_save(); +		$reparser->reparse_range(1, 1); +		$expected = array( +			array( +				'config_name'  => 'contact_admin_info', +				'config_value' => '<r><EMAIL email="admin@example.org"><s>[email]</s>admin@example.org<e>[/email]</e></EMAIL></r>', +			), +			array( +				'config_name'  => 'contact_admin_info_bitfield', +				'config_value' => 'ACA=', +			), +			array( +				'config_name'  => 'contact_admin_info_flags', +				'config_value' => '7', +			), +			array( +				'config_name'  => 'contact_admin_info_uid', +				'config_value' => '1a2hbwf5', +			), +		); +		$this->assertEquals($expected, $this->get_rows()); +	} +} diff --git a/tests/text_reparser/plugins/fixtures/contact_admin_info.xml b/tests/text_reparser/plugins/fixtures/contact_admin_info.xml new file mode 100644 index 0000000000..13cd82b1a4 --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/contact_admin_info.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_config_text"> +		<column>config_name</column> +		<column>config_value</column> +		<row> +			<value>contact_admin_info</value> +			<value>[email:1a2hbwf5]admin@example.org[/email:1a2hbwf5]</value> +		</row> +		<row> +			<value>contact_admin_info_uid</value> +			<value>1a2hbwf5</value> +		</row> +		<row> +			<value>contact_admin_info_bitfield</value> +			<value>ACA=</value> +		</row> +		<row> +			<value>contact_admin_info_flags</value> +			<value>7</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/forums.xml b/tests/text_reparser/plugins/fixtures/forums.xml new file mode 100644 index 0000000000..c12c8d6d48 --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/forums.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_forums"> +		<column>forum_id</column> +		<column>forum_parents</column> +		<column>forum_desc</column> +		<column>forum_desc_uid</column> +		<column>forum_desc_options</column> +		<column>forum_rules</column> +		<column>forum_rules_uid</column> +		<column>forum_rules_options</column> +		<row> +			<value>1</value> +			<value></value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +			<value>0</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +			<value>0</value> +		</row> +		<row> +			<value>2</value> +			<value></value> +			<value>[b]Not bold[/b] :) http://example.org</value> +			<value>abcd1234</value> +			<value>0</value> +			<value>[b]Not bold[/b] :) http://example.org</value> +			<value>abcd1234</value> +			<value>0</value> +		</row> +		<row> +			<value>3</value> +			<value></value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +			<value>abcd1234</value> +			<value>1</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +			<value>abcd1234</value> +			<value>1</value> +		</row> +		<row> +			<value>4</value> +			<value></value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +			<value>abcd1234</value> +			<value>2</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +			<value>abcd1234</value> +			<value>2</value> +		</row> +		<row> +			<value>5</value> +			<value></value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +			<value>abcd1234</value> +			<value>4</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +			<value>abcd1234</value> +			<value>4</value> +		</row> +		<row> +			<value>6</value> +			<value></value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +			<value>abcd1234</value> +			<value>1</value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +			<value>abcd1234</value> +			<value>1</value> +		</row> +		<row> +			<value>7</value> +			<value></value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +			<value>abcd1234</value> +			<value>0</value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +			<value>abcd1234</value> +			<value>0</value> +		</row> +		<row> +			<value>8</value> +			<value></value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +			<value>abcd1234</value> +			<value>1</value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +			<value>abcd1234</value> +			<value>1</value> +		</row> +		<row> +			<value>9</value> +			<value></value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +			<value>abcd1234</value> +			<value>0</value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +			<value>abcd1234</value> +			<value>0</value> +		</row> +		<row> +			<value>1000</value> +			<value></value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +			<value>0</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +			<value>0</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/groups.xml b/tests/text_reparser/plugins/fixtures/groups.xml new file mode 100644 index 0000000000..15151426bc --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/groups.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_groups"> +		<column>group_id</column> +		<column>group_desc</column> +		<column>group_desc_options</column> +		<column>group_desc_uid</column> +		<row> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>7</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>2</value> +			<value>[b]Not bold[/b] :) http://example.org</value> +			<value>0</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>3</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +			<value>1</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>4</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +			<value>2</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>5</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +			<value>4</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>6</value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +			<value>1</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>7</value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +			<value>1</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>8</value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +			<value>1</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>9</value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +			<value>1</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>1000</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>7</value> +			<value>abcd1234</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/poll_options.xml b/tests/text_reparser/plugins/fixtures/poll_options.xml new file mode 100644 index 0000000000..48ba024315 --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/poll_options.xml @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_poll_options"> +		<column>poll_option_id</column> +		<column>topic_id</column> +		<column>poll_option_text</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +		<row> +			<value>2</value> +			<value>1</value> +			<value>This row should be [b:abcd1234]ignored[/b:abcd1234]</value> +		</row> +		<row> +			<value>1</value> +			<value>2</value> +			<value>[b:abcd1234]Bold[/b:abcd1234]</value> +		</row> +		<row> +			<value>2</value> +			<value>2</value> +			<value><![CDATA[<!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) -->]]></value> +		</row> +		<row> +			<value>3</value> +			<value>2</value> +			<value><![CDATA[<!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +		</row> +		<row> +			<value>1</value> +			<value>11</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +		</row> +		<row> +			<value>1</value> +			<value>12</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +		</row> +		<row> +			<value>1</value> +			<value>13</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +		</row> +		<row> +			<value>1</value> +			<value>123</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +		<row> +			<value>2</value> +			<value>123</value> +			<value>This row should be [b:abcd1234]ignored[/b:abcd1234]</value> +		</row> +	</table> +	<table name="phpbb_posts"> +		<column>post_id</column> +		<column>enable_bbcode</column> +		<column>enable_smilies</column> +		<column>enable_magic_url</column> +		<column>post_text</column> +		<column>bbcode_uid</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>11</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>12</value> +			<value>0</value> +			<value>1</value> +			<value>0</value> +			<value></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>13</value> +			<value>0</value> +			<value>0</value> +			<value>1</value> +			<value></value> +			<value>abcd1234</value> +		</row> +	</table> +	<table name="phpbb_topics"> +		<column>topic_id</column> +		<column>topic_first_post_id</column> +		<column>poll_title</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +		<row> +			<value>2</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +		<row> +			<value>11</value> +			<value>11</value> +			<value>BBCode</value> +		</row> +		<row> +			<value>12</value> +			<value>12</value> +			<value>Smilies</value> +		</row> +		<row> +			<value>13</value> +			<value>13</value> +			<value>Magic URLs</value> +		</row> +		<row> +			<value>123</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/polls.xml b/tests/text_reparser/plugins/fixtures/polls.xml new file mode 100644 index 0000000000..2960d640a9 --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/polls.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_posts"> +		<column>post_id</column> +		<column>enable_bbcode</column> +		<column>enable_smilies</column> +		<column>enable_magic_url</column> +		<column>post_text</column> +		<column>bbcode_uid</column> +		<row> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>0</value> +			<value></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>2</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>3</value> +			<value>0</value> +			<value>1</value> +			<value>0</value> +			<value></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>4</value> +			<value>0</value> +			<value>0</value> +			<value>1</value> +			<value></value> +			<value>abcd1234</value> +		</row> +	</table> +	<table name="phpbb_topics"> +		<column>topic_id</column> +		<column>topic_first_post_id</column> +		<column>poll_title</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +		<row> +			<value>2</value> +			<value>1</value> +			<value>[b]Not bold[/b] :) http://example.org</value> +		</row> +		<row> +			<value>3</value> +			<value>2</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +		</row> +		<row> +			<value>4</value> +			<value>3</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +		</row> +		<row> +			<value>5</value> +			<value>4</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +		</row> +		<row> +			<value>6</value> +			<value>2</value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +		</row> +		<row> +			<value>7</value> +			<value>1</value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +		</row> +		<row> +			<value>8</value> +			<value>2</value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +		</row> +		<row> +			<value>9</value> +			<value>1</value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +		</row> +		<row> +			<value>1000</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/posts.xml b/tests/text_reparser/plugins/fixtures/posts.xml new file mode 100644 index 0000000000..ec31747ed9 --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/posts.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_posts"> +		<column>post_id</column> +		<column>enable_bbcode</column> +		<column>enable_smilies</column> +		<column>enable_magic_url</column> +		<column>post_text</column> +		<column>bbcode_uid</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>2</value> +			<value>0</value> +			<value>0</value> +			<value>0</value> +			<value>[b]Not bold[/b] :) http://example.org</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>3</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>4</value> +			<value>0</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>5</value> +			<value>0</value> +			<value>0</value> +			<value>1</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>6</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>7</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>8</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>9</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>1000</value> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/privmsgs.xml b/tests/text_reparser/plugins/fixtures/privmsgs.xml new file mode 100644 index 0000000000..4049b9890a --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/privmsgs.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_privmsgs"> +		<column>msg_id</column> +		<column>enable_bbcode</column> +		<column>enable_smilies</column> +		<column>enable_magic_url</column> +		<column>message_text</column> +		<column>bbcode_uid</column> +		<column>to_address</column> +		<column>bcc_address</column> +		<row> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>2</value> +			<value>0</value> +			<value>0</value> +			<value>0</value> +			<value>[b]Not bold[/b] :) http://example.org</value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>3</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>4</value> +			<value>0</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>5</value> +			<value>0</value> +			<value>0</value> +			<value>1</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>6</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>7</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>8</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>9</value> +			<value>1</value> +			<value>1</value> +			<value>0</value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>1000</value> +			<value>1</value> +			<value>1</value> +			<value>1</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +			<value></value> +			<value></value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/fixtures/users.xml b/tests/text_reparser/plugins/fixtures/users.xml new file mode 100644 index 0000000000..60c623b6b1 --- /dev/null +++ b/tests/text_reparser/plugins/fixtures/users.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_users"> +		<column>user_id</column> +		<column>user_permissions</column> +		<column>username_clean</column> +		<column>user_options</column> +		<column>user_sig</column> +		<column>user_sig_bbcode_uid</column> +		<row> +			<value>1</value> +			<value></value> +			<value>user1</value> +			<value>230271</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>2</value> +			<value></value> +			<value>user2</value> +			<value>895</value> +			<value>[b]Not bold[/b] :) http://example.org</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>3</value> +			<value></value> +			<value>user3</value> +			<value>33663</value> +			<value>[b:abcd1234]Bold[/b:abcd1234] :) http://example.org</value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>4</value> +			<value></value> +			<value>user4</value> +			<value>66431</value> +			<value><![CDATA[[b]Not bold[/b] <!-- s:) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":)" title="Smile" /><!-- s:) --> http://example.org]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>5</value> +			<value></value> +			<value>user5</value> +			<value>131967</value> +			<value><![CDATA[[b]Not bold[/b] :) <!-- m --><a class="postlink" href="http://example.org">http://example.org</a><!-- m -->]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>6</value> +			<value></value> +			<value>user6</value> +			<value>99199</value> +			<value><![CDATA[[flash=123,345:abcd1234]http://example.org/flash.swf[/flash:abcd1234]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>7</value> +			<value></value> +			<value>user7</value> +			<value>99199</value> +			<value><![CDATA[[flash=123,345]http://example.org/flash.swf[/flash]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>8</value> +			<value></value> +			<value>user8</value> +			<value>99199</value> +			<value><![CDATA[[img:abcd1234]http://example.org/img.png[/img:abcd1234]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>9</value> +			<value></value> +			<value>user9</value> +			<value>99199</value> +			<value><![CDATA[[img]http://example.org/img.png[/img]]]></value> +			<value>abcd1234</value> +		</row> +		<row> +			<value>1000</value> +			<value></value> +			<value>user1000</value> +			<value>230271</value> +			<value>This row should be [b]ignored[/b]</value> +			<value>abcd1234</value> +		</row> +	</table> +</dataset> diff --git a/tests/text_reparser/plugins/forum_description_test.php b/tests/text_reparser/plugins/forum_description_test.php new file mode 100644 index 0000000000..57166e6a3c --- /dev/null +++ b/tests/text_reparser/plugins/forum_description_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_forum_description_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\forum_description($this->db, FORUMS_TABLE); +	} +} diff --git a/tests/text_reparser/plugins/forum_rules_test.php b/tests/text_reparser/plugins/forum_rules_test.php new file mode 100644 index 0000000000..72e4e98876 --- /dev/null +++ b/tests/text_reparser/plugins/forum_rules_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_forum_rules_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/forums.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\forum_rules($this->db, FORUMS_TABLE); +	} +} diff --git a/tests/text_reparser/plugins/group_description_test.php b/tests/text_reparser/plugins/group_description_test.php new file mode 100644 index 0000000000..babfc7e02f --- /dev/null +++ b/tests/text_reparser/plugins/group_description_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_group_description_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/groups.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\group_description($this->db, GROUPS_TABLE); +	} +} diff --git a/tests/text_reparser/plugins/pm_text_test.php b/tests/text_reparser/plugins/pm_text_test.php new file mode 100644 index 0000000000..6dc1a9cb4c --- /dev/null +++ b/tests/text_reparser/plugins/pm_text_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_pm_text_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/privmsgs.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\pm_text($this->db, PRIVMSGS_TABLE); +	} +} diff --git a/tests/text_reparser/plugins/poll_option_test.php b/tests/text_reparser/plugins/poll_option_test.php new file mode 100644 index 0000000000..177faac51d --- /dev/null +++ b/tests/text_reparser/plugins/poll_option_test.php @@ -0,0 +1,129 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; + +class phpbb_textreparser_poll_option_test extends phpbb_database_test_case +{ +	protected $db; + +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/poll_options.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\poll_option($this->db); +	} + +	protected function get_rows() +	{ +		$sql = 'SELECT topic_id, poll_option_id, poll_option_text +			FROM ' . POLL_OPTIONS_TABLE . ' +			ORDER BY topic_id, poll_option_id'; +		$result = $this->db->sql_query($sql); +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); + +		return $rows; +	} + +	public function setUp() +	{ +		global $config; +		if (!isset($config)) +		{ +			$config = new \phpbb\config\config(array()); +		} +		$this->get_test_case_helpers()->set_s9e_services(); +		$this->db = $this->new_dbal(); +		parent::setUp(); +	} + +	public function test_get_max_id() +	{ +		$reparser = $this->get_reparser(); +		$this->assertEquals(123, $reparser->get_max_id()); +	} + +	public function test_dry_run() +	{ +		$old_rows = $this->get_rows(); +		$reparser = $this->get_reparser(); +		$reparser->disable_save(); +		$reparser->reparse_range(1, 1); +		$new_rows = $this->get_rows(); +		$this->assertEquals($old_rows, $new_rows); +	} + +	public function testReparse() +	{ +		$reparser = $this->get_reparser(); +		$reparser->enable_save(); +		$reparser->reparse_range(2, 13); +		$expected = array( +			array( +				'topic_id'         => 1, +				'poll_option_id'   => 1, +				'poll_option_text' => 'This row should be [b]ignored[/b]', +			), +			array( +				'topic_id'         => 1, +				'poll_option_id'   => 2, +				'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]', +			), +			array( +				'topic_id'         => 2, +				'poll_option_id'   => 1, +				'poll_option_text' => '<r><B><s>[b]</s>Bold<e>[/b]</e></B></r>', +			), +			array( +				'topic_id'         => 2, +				'poll_option_id'   => 2, +				'poll_option_text' => '<r><E>:)</E></r>', +			), +			array( +				'topic_id'         => 2, +				'poll_option_id'   => 3, +				'poll_option_text' => '<r><URL url="http://example.org">http://example.org</URL></r>', +			), +			array( +				'topic_id'         => 11, +				'poll_option_id'   => 1, +				'poll_option_text' => '<r><B><s>[b]</s>Bold<e>[/b]</e></B> :) http://example.org</r>', +			), +			array( +				'topic_id'         => 12, +				'poll_option_id'   => 1, +				'poll_option_text' => '<r>[b]Not bold[/b] <E>:)</E> http://example.org</r>', +			), +			array( +				'topic_id'         => 13, +				'poll_option_id'   => 1, +				'poll_option_text' => '<r>[b]Not bold[/b] :) <URL url="http://example.org">http://example.org</URL></r>', +			), +			array( +				'topic_id'         => 123, +				'poll_option_id'   => 1, +				'poll_option_text' => 'This row should be [b]ignored[/b]', +			), +			array( +				'topic_id'         => 123, +				'poll_option_id'   => 2, +				'poll_option_text' => 'This row should be [b:abcd1234]ignored[/b:abcd1234]', +			), +		); +		$this->assertEquals($expected, $this->get_rows()); +	} +} diff --git a/tests/text_reparser/plugins/poll_title_test.php b/tests/text_reparser/plugins/poll_title_test.php new file mode 100644 index 0000000000..046b6019c8 --- /dev/null +++ b/tests/text_reparser/plugins/poll_title_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_poll_title_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/polls.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\poll_title($this->db, TOPICS_TABLE); +	} +} diff --git a/tests/text_reparser/plugins/post_text_test.php b/tests/text_reparser/plugins/post_text_test.php new file mode 100644 index 0000000000..8ea71e65f5 --- /dev/null +++ b/tests/text_reparser/plugins/post_text_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_post_text_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/posts.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\post_text($this->db, POSTS_TABLE); +	} +} diff --git a/tests/text_reparser/plugins/test_row_based_plugin.php b/tests/text_reparser/plugins/test_row_based_plugin.php new file mode 100644 index 0000000000..3e9ff09448 --- /dev/null +++ b/tests/text_reparser/plugins/test_row_based_plugin.php @@ -0,0 +1,150 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../../test_framework/phpbb_database_test_case.php'; + +abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_test_case +{ +	protected $db; + +	abstract protected function get_reparser(); + +	protected function get_rows(array $ids) +	{ +		$reparser = $this->get_reparser(); +		$columns = $reparser->get_columns(); + +		$reflection_reparser = new ReflectionClass(get_class($reparser)); +		$table_property = $reflection_reparser->getProperty('table'); +		$table_property->setAccessible(true); + +		$sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text +			FROM ' . $table_property->getValue($reparser) . ' +			WHERE ' . $this->db->sql_in_set($columns['id'], $ids) . ' +			ORDER BY id'; +		$result = $this->db->sql_query($sql); +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); + +		return $rows; +	} + +	public function setUp() +	{ +		global $config; +		if (!isset($config)) +		{ +			$config = new \phpbb\config\config(array()); +		} +		$this->get_test_case_helpers()->set_s9e_services(); +		$this->db = $this->new_dbal(); +		parent::setUp(); +	} + +	public function test_get_max_id() +	{ +		$reparser = $this->get_reparser(); +		$this->assertEquals(1000, $reparser->get_max_id()); +	} + +	public function test_dry_run() +	{ +		$old_rows = $this->get_rows(array(1)); +		$reparser = $this->get_reparser(); +		$reparser->disable_save(); +		$reparser->reparse_range(1, 1); +		$new_rows = $this->get_rows(array(1)); +		$this->assertEquals($old_rows, $new_rows); +	} + +	/** +	* @dataProvider get_reparse_tests +	*/ +	public function test_reparse($min_id, $max_id, $expected) +	{ +		$reparser = $this->get_reparser(); +		$reparser->reparse_range($min_id, $max_id); + +		$ids = array(); +		foreach ($expected as $row) +		{ +			$ids[] = $row['id']; +		} + +		$this->assertEquals($expected, $this->get_rows($ids)); +	} + +	public function get_reparse_tests() +	{ +		return array( +			array( +				2, +				5, +				array( +					array( +						'id'   => '1', +						'text' => 'This row should be [b]ignored[/b]', +					), +					array( +						'id'   => '2', +						'text' => '<t>[b]Not bold[/b] :) http://example.org</t>', +					), +					array( +						'id'   => '3', +						'text' => '<r><B><s>[b]</s>Bold<e>[/b]</e></B> :) http://example.org</r>', +					), +					array( +						'id'   => '4', +						'text' => '<r>[b]Not bold[/b] <E>:)</E> http://example.org</r>', +					), +					array( +						'id'   => '5', +						'text' => '<r>[b]Not bold[/b] :) <URL url="http://example.org">http://example.org</URL></r>', +					), +					array( +						'id'   => '1000', +						'text' => 'This row should be [b]ignored[/b]', +					), +				) +			), +			array( +				6, +				7, +				array( +					array( +						'id'   => '6', +						'text' => '<r><FLASH height="345" url="http://example.org/flash.swf" width="123"><s>[flash=123,345]</s>http://example.org/flash.swf<e>[/flash]</e></FLASH></r>', +					), +					array( +						'id'   => '7', +						'text' => '<t>[flash=123,345]http://example.org/flash.swf[/flash]</t>', +					), +				) +			), +			array( +				8, +				9, +				array( +					array( +						'id'   => '8', +						'text' => '<r><IMG src="http://example.org/img.png"><s>[img]</s>http://example.org/img.png<e>[/img]</e></IMG></r>', +					), +					array( +						'id'   => '9', +						'text' => '<t>[img]http://example.org/img.png[/img]</t>', +					), +				) +			), +		); +	} +} diff --git a/tests/text_reparser/plugins/user_signature_test.php b/tests/text_reparser/plugins/user_signature_test.php new file mode 100644 index 0000000000..5b66f2788a --- /dev/null +++ b/tests/text_reparser/plugins/user_signature_test.php @@ -0,0 +1,26 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ +include_once __DIR__ . '/test_row_based_plugin.php'; + +class phpbb_textreparser_user_signature_test extends phpbb_textreparser_test_row_based_plugin +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(__DIR__ . '/fixtures/users.xml'); +	} + +	protected function get_reparser() +	{ +		return new \phpbb\textreparser\plugins\user_signature($this->db, USERS_TABLE); +	} +} diff --git a/tests/tree/nestedset_forum_base.php b/tests/tree/nestedset_forum_base.php index c56be1f81e..3daa75b2e4 100644 --- a/tests/tree/nestedset_forum_base.php +++ b/tests/tree/nestedset_forum_base.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_tests_tree_nestedset_forum_base extends phpbb_database_test_case  {  	public function getDataSet() @@ -59,7 +57,6 @@ class phpbb_tests_tree_nestedset_forum_base extends phpbb_database_test_case  		global $config;  		$config = $this->config = new \phpbb\config\config(array('nestedset_forum_lock' => 0)); -		set_config(null, null, null, $this->config);  		$this->lock = new \phpbb\lock\db('nestedset_forum_lock', $this->config, $this->db);  		$this->set = new \phpbb\tree\nestedset_forum($this->db, $this->lock, 'phpbb_forums'); diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php new file mode 100644 index 0000000000..3501124fc1 --- /dev/null +++ b/tests/ui/permission_roles_test.php @@ -0,0 +1,90 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group ui +*/ +class ui_permission_roles_test extends phpbb_ui_test_case +{ + +	public function test_permission_roles() +	{ +		$this->login(); +		$this->admin_login(); +		$this->add_lang('acp/permissions'); +		$this->visit('adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid); + +		// Select forums +		$elements = self::find_element('cssSelector', 'select#forum') +			->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); + +		foreach ($elements as $element) +		{ +			$element->click(); +		} +		self::find_element('cssSelector', 'form#select_victim') +			->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=submit]')) +			->click(); + +		// Select administrators and guests +		$groups_form = self::find_element('cssSelector', 'form#groups'); +		$elements = $groups_form +			->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('select')) +			->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); + +		foreach ($elements as $element) +		{ +			if ($element->getText() === 'Administrators' || $element->getText() === 'Guests') +			{ +				$element->click(); +			} +		} +		$groups_form->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[name=submit_edit_options]'))->click(); + +		$first_fieldset = self::find_element('cssSelector', '#perm11'); +		$this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); +		$first_fieldset +			->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle')) +			->click(); +		$this->assertEquals('block', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); +		$lis = $first_fieldset +			->findElements(\Facebook\WebDriver\WebDriverBy::cssSelector('ul > li')); + +		foreach ($lis as $li) +		{ +			if ($li->getAttribute('data-id') == 18) +			{ +				$li->click(); + +				break; +			} +		} +		$this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); +		$this->assertEquals(18, $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); +		$this->assertEquals($this->lang('ROLE_FORUM_LIMITED'), $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); + +		// Check that admin settings didn't get changed +		$second_fieldset = self::find_element('cssSelector', '#perm10'); +		$this->assertEquals('none', $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); +		// Full access = 14 +		$this->assertEquals(14, $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); +		$this->assertEquals($this->lang('ROLE_FORUM_FULL'), $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); + +		// Check that category settings were not modified +		$category_fieldset = self::find_element('cssSelector', '#perm00'); +		$this->assertEquals('none', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); +		// No settings +		$this->assertEquals('', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); +		$this->assertEquals($this->lang('NO_ROLE_ASSIGNED'), $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); +	} +} diff --git a/tests/ui/quick_links_test.php b/tests/ui/quick_links_test.php index 5bddb44a8b..582aeafcae 100644 --- a/tests/ui/quick_links_test.php +++ b/tests/ui/quick_links_test.php @@ -16,7 +16,6 @@  */  class quick_links_test extends phpbb_ui_test_case  { -  	public function test_quick_links()  	{  		$this->visit('index.php'); diff --git a/tests/upload/filespec_test.php b/tests/upload/filespec_test.php index ed28bcb38f..18b6deed1f 100644 --- a/tests/upload/filespec_test.php +++ b/tests/upload/filespec_test.php @@ -11,10 +11,6 @@  *  */ -require_once __DIR__ . '/../../phpBB/includes/functions.php'; -require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php'; -require_once __DIR__ . '/../../phpBB/includes/functions_upload.php'; -  class phpbb_filespec_test extends phpbb_test_case  {  	const TEST_COUNT = 100; @@ -23,14 +19,19 @@ class phpbb_filespec_test extends phpbb_test_case  	const UPLOAD_MAX_FILESIZE = 1000;  	private $config; +	private $filesystem;  	public $path; +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; +  	protected function setUp()  	{  		// Global $config required by unique_id -		// Global $user required by filespec::additional_checks and -		// filespec::move_file -		global $config, $user; +		global $config, $phpbb_root_path, $phpEx;  		if (!is_array($config))  		{ @@ -44,9 +45,6 @@ class phpbb_filespec_test extends phpbb_test_case  		// See: phpBB/install/schemas/schema_data.sql  		$config['mime_triggers'] = 'body|head|html|img|plaintext|a href|pre|script|table|title'; -		$user = new phpbb_mock_user(); -		$user->lang = new phpbb_mock_lang(); -  		$this->config = &$config;  		$this->path = __DIR__ . '/fixture/'; @@ -75,6 +73,17 @@ class phpbb_filespec_test extends phpbb_test_case  		$guessers[2]->set_priority(-2);  		$guessers[3]->set_priority(-2);  		$this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	private function set_reflection_property(&$class, $property_name, $value) +	{ +		$property = new ReflectionProperty($class, $property_name); +		$property->setAccessible(true); +		$property->setValue($class, $value);  	}  	private function get_filespec($override = array()) @@ -88,14 +97,13 @@ class phpbb_filespec_test extends phpbb_test_case  			'error' => '',  		); -		return new filespec(array_merge($upload_ary, $override), null, $this->mimetype_guesser); +		$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser); +		return $filespec->set_upload_ary(array_merge($upload_ary, $override));  	}  	protected function tearDown()  	{ -		global $user;  		$this->config = array(); -		$user = null;  		$iterator = new DirectoryIterator($this->path . 'copies');  		foreach ($iterator as $fileinfo) @@ -108,6 +116,13 @@ class phpbb_filespec_test extends phpbb_test_case  		}  	} +	public function test_empty_upload_ary() +	{ +		$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser); +		$this->assertInstanceOf('\phpbb\files\filespec', $filespec->set_upload_ary(array())); +		$this->assertTrue($filespec->init_error()); +	} +  	public function additional_checks_variables()  	{  		// False here just indicates the file is too large and fails the @@ -129,13 +144,26 @@ class phpbb_filespec_test extends phpbb_test_case  	{  		$upload = new phpbb_mock_fileupload();  		$filespec = $this->get_filespec(); -		$filespec->upload = $upload; -		$filespec->file_moved = true; -		$filespec->filesize = $filespec->get_filesize($this->path . $filename); +		$filespec->set_upload_namespace($upload); +		$this->set_reflection_property($filespec, 'file_moved', true); +		$this->set_reflection_property($filespec, 'filesize', $filespec->get_filesize($this->path . $filename));  		$this->assertEquals($expected, $filespec->additional_checks());  	} +	public function test_additional_checks_dimensions() +	{ +		$upload = new phpbb_mock_fileupload(); +		$filespec = $this->get_filespec(); +		$filespec->set_upload_namespace($upload); +		$upload->valid_dimensions = false; +		$this->set_reflection_property($filespec, 'file_moved', true); +		$upload->max_filesize = 0; + +		$this->assertEquals(false, $filespec->additional_checks()); +		$this->assertSame(array('WRONG_SIZE'), $filespec->error); +	} +  	public function check_content_variables()  	{  		// False here indicates that a file is non-binary and contains @@ -170,6 +198,7 @@ class phpbb_filespec_test extends phpbb_test_case  			array($chunks[2] . $chunks[9]),  			array($chunks[3] . $chunks[4]),  			array($chunks[5] . $chunks[6]), +			array('foobar.png'),  		);  	} @@ -181,7 +210,7 @@ class phpbb_filespec_test extends phpbb_test_case  		$bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');  		$filespec = $this->get_filespec(array('name' => $filename));  		$filespec->clean_filename('real', self::PREFIX); -		$name = $filespec->realname; +		$name = $filespec->get('realname');  		$this->assertEquals(0, preg_match('/%(\w{2})/', $name));  		foreach ($bad_chars as $char) @@ -197,8 +226,8 @@ class phpbb_filespec_test extends phpbb_test_case  		{  			$filespec = $this->get_filespec();  			$filespec->clean_filename('unique', self::PREFIX); -			$name = $filespec->realname; -			 +			$name = $filespec->get('realname'); +  			$this->assertEquals(strlen($name), 32 + strlen(self::PREFIX));  			$this->assertRegExp('#^[A-Za-z0-9]+$#', substr($name, strlen(self::PREFIX)));  			$this->assertFalse(isset($filenames[$name])); @@ -206,6 +235,55 @@ class phpbb_filespec_test extends phpbb_test_case  		}  	} +	public function test_clean_filename_unique_ext() +	{ +		$filenames = array(); +		for ($tests = 0; $tests < self::TEST_COUNT; $tests++) +		{ +			$filespec = $this->get_filespec(array('name' => 'foobar.jpg')); +			$filespec->clean_filename('unique_ext', self::PREFIX); +			$name = $filespec->get('realname'); + +			$this->assertEquals(strlen($name), 32 + strlen(self::PREFIX) + strlen('.jpg')); +			$this->assertRegExp('#^[A-Za-z0-9]+\.jpg$#', substr($name, strlen(self::PREFIX))); +			$this->assertFalse(isset($filenames[$name])); +			$filenames[$name] = true; +		} +	} + +	public function data_clean_filename_avatar() +	{ +		return array( +			array(false, false, ''), +			array('foobar.png', 'u5.png', 'avatar', 'u', 5), +			array('foobar.png', 'g9.png', 'avatar', 'g', 9), + +		); +	} + +	/** +	 * @dataProvider data_clean_filename_avatar +	 */ +	public function test_clean_filename_avatar($filename, $expected, $mode, $prefix = '', $user_id = '') +	{ +		$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser); + +		if ($filename) +		{ +			$upload_ary = array( +				'name' => $filename, +				'type' => '', +				'size' => '', +				'tmp_name' => '', +				'error' => '', +			); +			$filespec->set_upload_ary($upload_ary); +		} +		$filespec->clean_filename($mode, $prefix, $user_id); + +		$this->assertSame($expected, $filespec->get('realname')); +	} +  	public function get_extension_variables()  	{  		return array( @@ -223,7 +301,7 @@ class phpbb_filespec_test extends phpbb_test_case  	 */  	public function test_get_extension($filename, $expected)  	{ -		$this->assertEquals($expected, filespec::get_extension($filename)); +		$this->assertEquals($expected, \phpbb\files\filespec::get_extension($filename));  	}  	public function is_image_variables() @@ -286,7 +364,7 @@ class phpbb_filespec_test extends phpbb_test_case  			array('txt_copy', 'txt_as_img', 'image/jpg', 'txt', false, true),  			array('txt_copy_2', 'txt_moved', 'text/plain', 'txt', false, true),  			array('jpg_copy', 'jpg_moved', 'image/png', 'jpg', false, true), -			array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH', true), +			array('png_copy', 'png_moved', 'image/png', 'jpg', 'Image file type mismatch: expected extension png but extension jpg given.', true),  		);  	} @@ -297,8 +375,7 @@ class phpbb_filespec_test extends phpbb_test_case  	{  		// Global $phpbb_root_path and $phpEx are required by phpbb_chmod  		global $phpbb_root_path, $phpEx; -		$phpbb_root_path = ''; -		$phpEx = 'php'; +		$this->phpbb_root_path = '';  		$upload = new phpbb_mock_fileupload();  		$upload->max_filesize = self::UPLOAD_MAX_FILESIZE; @@ -308,18 +385,137 @@ class phpbb_filespec_test extends phpbb_test_case  			'name' => $realname,  			'type' => $mime_type,  		)); -		$filespec->extension = $extension; -		$filespec->upload = $upload; -		$filespec->local = true; +		$this->set_reflection_property($filespec, 'extension', $extension); +		$filespec->set_upload_namespace($upload); +		$this->set_reflection_property($filespec, 'local', true);  		$this->assertEquals($expected, $filespec->move_file($this->path . 'copies')); -		$this->assertEquals($filespec->file_moved, file_exists($this->path . 'copies/' . $realname)); +		$this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/' . $realname));  		if ($error)  		{  			$this->assertEquals($error, $filespec->error[0]);  		} -		$phpEx = ''; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function test_move_file_error() +	{ +		$filespec = $this->get_filespec(); +		$this->assertFalse($filespec->move_file('foobar')); +		$filespec->error[] = 'foo'; +		$this->assertFalse($filespec->move_file('foo')); +	} + +	public function data_move_file_copy() +	{ +		return array( +			array('gif_copy', true, false, array()), +			array('gif_copy', true, true, array()), +			array('foo_bar', false, false, array('GENERAL_UPLOAD_ERROR')), +			array('foo_bar', false, true, array('GENERAL_UPLOAD_ERROR')), +		); +	} + +	/** +	 * @dataProvider data_move_file_copy +	 */ +	public function test_move_file_copy($tmp_name, $move_success, $safe_mode_on, $expected_error) +	{ +		// Initialise a blank filespec object for use with trivial methods +		$upload_ary = array( +			'name' => 'gif_moved', +			'type' => 'image/gif', +			'size' => '', +			'tmp_name' => $this->path . 'copies/' . $tmp_name, +			'error' => '', +		); + +		$php_ini = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper') +			->getMock(); +		$php_ini->expects($this->any()) +			->method('getBool') +			->with($this->anything()) +			->willReturn($safe_mode_on); +		$upload = new phpbb_mock_fileupload(); +		$upload->max_filesize = self::UPLOAD_MAX_FILESIZE; +		$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, $php_ini, new \FastImageSize\FastImagesize,  '', $this->mimetype_guesser); +		$filespec->set_upload_ary($upload_ary); +		$this->set_reflection_property($filespec, 'local', false); +		$this->set_reflection_property($filespec, 'extension', 'gif'); +		$filespec->set_upload_namespace($upload); + +		$this->assertEquals($move_success, $filespec->move_file($this->path . 'copies')); +		$this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/gif_moved')); +		$this->assertSame($expected_error, $filespec->error); +	} + +	public function data_move_file_imagesize() +	{ +		return array( +			array( +				array( +					'width'		=> 2, +					'height'	=> 2, +					'type'		=> IMAGETYPE_GIF, +				), +				array() +			), +			array( +				array( +					'width'		=> 2, +					'height'	=> 2, +					'type'		=> -1, +				), +				array('Image file type -1 for mimetype image/gif not supported.') +			), +			array( +				array( +					'width'		=> 0, +					'height'	=> 0, +					'type'		=> IMAGETYPE_GIF, +				), +				array('The image file you tried to attach is invalid.') +			), +			array( +				false, +				array('It was not possible to determine the dimensions of the image. Please verify that the URL you entered is correct.') +			) +		); +	} + +	/** +	 * @dataProvider data_move_file_imagesize +	 */ +	public function test_move_file_imagesize($imagesize_return, $expected_error) +	{ +		// Initialise a blank filespec object for use with trivial methods +		$upload_ary = array( +			'name' => 'gif_moved', +			'type' => 'image/gif', +			'size' => '', +			'tmp_name' => $this->path . 'copies/gif_copy', +			'error' => '', +		); + +		$imagesize = $this->getMockBuilder('\FastImageSize\FastImageSize') +			->getMock(); +		$imagesize->expects($this->any()) +			->method('getImageSize') +			->with($this->anything()) +			->willReturn($imagesize_return); + +		$upload = new phpbb_mock_fileupload(); +		$upload->max_filesize = self::UPLOAD_MAX_FILESIZE; +		$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, $imagesize,  '', $this->mimetype_guesser); +		$filespec->set_upload_ary($upload_ary); +		$this->set_reflection_property($filespec, 'local', false); +		$this->set_reflection_property($filespec, 'extension', 'gif'); +		$filespec->set_upload_namespace($upload); + +		$this->assertEquals(true, $filespec->move_file($this->path . 'copies')); +		$this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/gif_moved')); +		$this->assertSame($expected_error, $filespec->error);  	}  	/** @@ -333,6 +529,29 @@ class phpbb_filespec_test extends phpbb_test_case  		$type_cast_helper->set_var($upload_name, $filename, 'string', true, true);  		$filespec = $this->get_filespec(array('name'=> $upload_name)); -		$this->assertSame(trim(utf8_basename(htmlspecialchars($filename))), $filespec->uploadname); +		$this->assertSame(trim(utf8_basename(htmlspecialchars($filename))), $filespec->get('uploadname')); +	} + +	public function test_is_uploaded() +	{ +		$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, null); +		$reflection_filespec = new ReflectionClass($filespec); +		$plupload_property = $reflection_filespec->getProperty('plupload'); +		$plupload_property->setAccessible(true); +		$plupload_mock = $this->getMockBuilder('\phpbb\plupload\plupload') +			->disableOriginalConstructor() +			->getMock(); +		$plupload_mock->expects($this->any()) +			->method('is_active') +			->will($this->returnValue(true)); +		$plupload_property->setValue($filespec, $plupload_mock); +		$is_uploaded = $reflection_filespec->getMethod('is_uploaded'); + +		// Plupload is active and file does not exist +		$this->assertFalse($is_uploaded->invoke($filespec)); + +		// Plupload is not active and file was not uploaded +		$plupload_property->setValue($filespec, null); +		$this->assertFalse($is_uploaded->invoke($filespec));  	}  } diff --git a/tests/upload/fileupload_test.php b/tests/upload/fileupload_test.php index fcfb84125d..fb72823f08 100644 --- a/tests/upload/fileupload_test.php +++ b/tests/upload/fileupload_test.php @@ -11,36 +11,88 @@  *  */ -require_once __DIR__ . '/../../phpBB/includes/functions.php'; -require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php'; -require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';  require_once __DIR__ . '/../mock/filespec.php';  class phpbb_fileupload_test extends phpbb_test_case  {  	private $path; +	private $filesystem; + +	/** @var \Symfony\Component\DependencyInjection\ContainerInterface */ +	protected $container; + +	/** @var \phpbb\files\factory */ +	protected $factory; + +	/** @var \bantu\IniGetWrapper\IniGetWrapper */ +	protected $php_ini; + +	/** @var \phpbb\language\language */ +	protected $language; + +	/** @var \phpbb\request\request_interface */ +	protected $request; + +	/** @var string phpBB root path */ +	protected $phpbb_root_path; +  	protected function setUp()  	{  		// Global $config required by unique_id -		// Global $user required by several functions dealing with translations -		// Global $request required by form_upload, local_upload and is_valid -		global $config, $user, $request; +		global $config, $phpbb_root_path, $phpEx;  		if (!is_array($config))  		{ -			$config = array(); +			$config = new \phpbb\config\config(array());  		}  		$config['rand_seed'] = '';  		$config['rand_seed_last_update'] = time() + 600; -		$user = new phpbb_mock_user(); -		$user->lang = new phpbb_mock_lang(); - -		$request = new phpbb_mock_request(); +		$this->request = $this->getMock('\phpbb\request\request'); +		$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; + +		$this->filesystem = new \phpbb\filesystem\filesystem(); +		$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +		$guessers = array( +			new \Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser(), +			new \Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser(), +			new \phpbb\mimetype\content_guesser(), +			new \phpbb\mimetype\extension_guesser(), +		); +		$guessers[2]->set_priority(-2); +		$guessers[3]->set_priority(-2); +		$this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers); + +		$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx); +		$this->container->set('files.filespec', new \phpbb\files\filespec( +			$this->filesystem, +			$this->language, +			$this->php_ini, +			new \FastImageSize\FastImageSize(), +			$phpbb_root_path, +			new \phpbb\mimetype\guesser(array( +				'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(), +			)))); +		$this->factory = new \phpbb\files\factory($this->container); +		$plupload = new \phpbb\plupload\plupload($phpbb_root_path, $config, $this->request, new \phpbb\user($this->language, '\phpbb\datetime'), $this->php_ini, $this->mimetype_guesser); +		$this->container->set('files.types.form', new \phpbb\files\types\form( +			$this->factory, +			$this->language, +			$this->php_ini, +			$plupload, +			$this->request +		), phpbb_mock_container_builder::SCOPE_PROTOTYPE); +		$this->container->set('files.types.local', new \phpbb\files\types\local( +			$this->factory, +			$this->language, +			$this->php_ini, +			$this->request +		), phpbb_mock_container_builder::SCOPE_PROTOTYPE);  		$this->path = __DIR__ . '/fixture/'; +		$this->phpbb_root_path = $phpbb_root_path;  	}  	private function gen_valid_filespec() @@ -65,15 +117,38 @@ class phpbb_fileupload_test extends phpbb_test_case  	public function test_common_checks_invalid_extension()  	{ -		$upload = new fileupload('', array('png'), 100); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('png')) +			->set_max_filesize(100);  		$file = $this->gen_valid_filespec();  		$upload->common_checks($file);  		$this->assertEquals('DISALLOWED_EXTENSION', $file->error[0]);  	} +	public function test_common_checks_disallowed_content() +	{ +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(1000); +		$file = new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path); +		$file->set_upload_ary(array( +				'size'	=> 50, +				'tmp_name'	=> dirname(__FILE__) . '/fixture/disallowed', +				'name'		=> 'disallowed.jpg', +				'type'		=> 'image/jpg' +			)) +			->set_upload_namespace($upload); +		file_put_contents(dirname(__FILE__) . '/fixture/disallowed', '<body>' . file_get_contents(dirname(__FILE__) . '/fixture/jpg')); +		$upload->common_checks($file); +		$this->assertEquals('DISALLOWED_CONTENT', $file->error[0]); +		unlink(dirname(__FILE__) . '/fixture/disallowed'); +	} +  	public function test_common_checks_invalid_filename()  	{ -		$upload = new fileupload('', array('jpg'), 100); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(100);  		$file = $this->gen_valid_filespec();  		$file->realname = 'invalid?';  		$upload->common_checks($file); @@ -82,7 +157,9 @@ class phpbb_fileupload_test extends phpbb_test_case  	public function test_common_checks_too_large()  	{ -		$upload = new fileupload('', array('jpg'), 100); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(100);  		$file = $this->gen_valid_filespec();  		$file->filesize = 1000;  		$upload->common_checks($file); @@ -91,7 +168,9 @@ class phpbb_fileupload_test extends phpbb_test_case  	public function test_common_checks_valid_file()  	{ -		$upload = new fileupload('', array('jpg'), 1000); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(1000);  		$file = $this->gen_valid_filespec();  		$upload->common_checks($file);  		$this->assertEquals(0, sizeof($file->error)); @@ -99,33 +178,41 @@ class phpbb_fileupload_test extends phpbb_test_case  	public function test_local_upload()  	{ -		$upload = new fileupload('', array('jpg'), 1000); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(1000);  		copy($this->path . 'jpg', $this->path . 'jpg.jpg'); -		$file = $upload->local_upload($this->path . 'jpg.jpg'); +		$file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');  		$this->assertEquals(0, sizeof($file->error)); -		unlink($this->path . 'jpg.jpg'); +		$this->assertFalse($file->additional_checks()); +		$this->assertTrue($file->move_file('../tests/upload/fixture/copies', true)); +		$file->remove();  	}  	public function test_move_existent_file()  	{ -		$upload = new fileupload('', array('jpg'), 1000); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(1000);  		copy($this->path . 'jpg', $this->path . 'jpg.jpg'); -		$file = $upload->local_upload($this->path . 'jpg.jpg'); +		$file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');  		$this->assertEquals(0, sizeof($file->error));  		$this->assertFalse($file->move_file('../tests/upload/fixture')); -		$this->assertFalse($file->file_moved); +		$this->assertFalse($file->get('file_moved'));  		$this->assertEquals(1, sizeof($file->error));  	}  	public function test_move_existent_file_overwrite()  	{ -		$upload = new fileupload('', array('jpg'), 1000); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(array('jpg')) +			->set_max_filesize(1000);  		copy($this->path . 'jpg', $this->path . 'jpg.jpg');  		copy($this->path . 'jpg', $this->path . 'copies/jpg.jpg'); -		$file = $upload->local_upload($this->path . 'jpg.jpg'); +		$file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');  		$this->assertEquals(0, sizeof($file->error));  		$file->move_file('../tests/upload/fixture/copies', true);  		$this->assertEquals(0, sizeof($file->error)); @@ -134,7 +221,10 @@ class phpbb_fileupload_test extends phpbb_test_case  	public function test_valid_dimensions()  	{ -		$upload = new fileupload('', false, false, 1, 1, 100, 100); +		$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); +		$upload->set_allowed_extensions(false) +			->set_max_filesize(false) +			->set_allowed_dimensions(1, 1, 100, 100);  		$file1 = $this->gen_valid_filespec();  		$file2 = $this->gen_valid_filespec(); diff --git a/tests/upload/fixture/bmp b/tests/upload/fixture/bmp Binary files differnew file mode 100644 index 0000000000..04bff561ab --- /dev/null +++ b/tests/upload/fixture/bmp diff --git a/tests/upload/fixture/iff b/tests/upload/fixture/iff Binary files differnew file mode 100644 index 0000000000..24eda8f593 --- /dev/null +++ b/tests/upload/fixture/iff diff --git a/tests/upload/fixture/iff_maya b/tests/upload/fixture/iff_maya Binary files differnew file mode 100644 index 0000000000..b6fb85101b --- /dev/null +++ b/tests/upload/fixture/iff_maya diff --git a/tests/upload/fixture/jp2 b/tests/upload/fixture/jp2 Binary files differnew file mode 100644 index 0000000000..adca6ecf0e --- /dev/null +++ b/tests/upload/fixture/jp2 diff --git a/tests/upload/fixture/jpx b/tests/upload/fixture/jpx Binary files differnew file mode 100644 index 0000000000..adca6ecf0e --- /dev/null +++ b/tests/upload/fixture/jpx diff --git a/tests/upload/fixture/psd b/tests/upload/fixture/psd Binary files differnew file mode 100644 index 0000000000..d1bc9a6a70 --- /dev/null +++ b/tests/upload/fixture/psd diff --git a/tests/upload/fixture/tif_compressed b/tests/upload/fixture/tif_compressed Binary files differnew file mode 100644 index 0000000000..133b50c4f0 --- /dev/null +++ b/tests/upload/fixture/tif_compressed diff --git a/tests/upload/fixture/tif_msb b/tests/upload/fixture/tif_msb Binary files differnew file mode 100644 index 0000000000..32eb8abfbb --- /dev/null +++ b/tests/upload/fixture/tif_msb diff --git a/tests/upload/fixture/wbmp b/tests/upload/fixture/wbmp Binary files differnew file mode 100644 index 0000000000..708c86ccee --- /dev/null +++ b/tests/upload/fixture/wbmp diff --git a/tests/upload/imagesize_test.php b/tests/upload/imagesize_test.php new file mode 100644 index 0000000000..5429bb5c5e --- /dev/null +++ b/tests/upload/imagesize_test.php @@ -0,0 +1,97 @@ +<?php + +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +class phpbb_upload_imagesize_test extends \phpbb_test_case +{ +	/** @var \FastImageSize\FastImageSize */ +	protected $imagesize; + +	/** @var string Path to fixtures */ +	protected $path; + +	public function setUp() +	{ +		parent::setUp(); +		$this->imagesize = new \FastImageSize\FastImageSize(); +		$this->path = __DIR__ . '/fixture/'; +	} + +	public function data_get_imagesize() +	{ +		return array( +			array('foobar', 'image/bmp', false), +			array('png', 'image/png', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)), +			array('gif', 'image/png', false), +			array('png', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)), +			array('gif', 'image/gif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)), +			array('jpg', 'image/gif', false), +			array('gif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)), +			array('jpg', 'image/jpg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)), +			array('jpg', 'image/jpeg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)), +			array('png', 'image/jpg', false), +			array('jpg', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)), +			array('psd', 'image/psd', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)), +			array('psd', 'image/photoshop', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)), +			array('jpg', 'image/psd', false), +			array('psd', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)), +			array('bmp', 'image/bmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)), +			array('png', 'image/bmp', false), +			array('bmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)), +			array('tif', 'image/tif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), +			array('png', 'image/tif', false), +			array('tif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), +			array('tif_compressed', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), +			array('png', 'image/tiff', false), +			array('tif_compressed', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)), +			array('tif_msb', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)), +			array('tif_msb', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)), +			array('wbmp', 'image/wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)), +			array('wbmp', 'image/vnd.wap.wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)), +			array('png', 'image/vnd.wap.wbmp', false), +			array('wbmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)), +			array('iff', 'image/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), +			array('iff', 'image/x-iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), +			array('iff_maya', 'iamge/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), +			array('png', 'image/iff', false), +			array('png', 'image/x-iff', false), +			array('iff', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), +			array('iff_maya', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)), +			array('jp2', 'image/jp2', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), +			array('jp2', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), +			array('jp2', 'image/jpm', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), +			array('jpg', 'image/jp2', false), +			array('jpx', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), +			array('jp2', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), +			array('jpx', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)), +		); +	} + +	/** +	 * @dataProvider data_get_imagesize +	 */ +	public function test_get_imagesize($file, $mime_type, $expected) +	{ +		$this->assertEquals($expected, $this->imagesize->getImageSize($this->path . $file, $mime_type)); +	} + +	public function test_get_imagesize_remote() +	{ +		$this->assertSame(array( +			'width'		=> 80, +			'height'	=> 80, +			'type'		=> IMAGETYPE_JPEG, +		), +		$this->imagesize->getImageSize('https://secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg')); +	} +} diff --git a/tests/user/lang_test.php b/tests/user/lang_test.php deleted file mode 100644 index bb11bb63cb..0000000000 --- a/tests/user/lang_test.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php -/** -* -* This file is part of the phpBB Forum Software package. -* -* @copyright (c) phpBB Limited <https://www.phpbb.com> -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; - -class phpbb_user_lang_test extends phpbb_test_case -{ -	public function test_user_lang_sprintf() -	{ -		$user = new \phpbb\user('\phpbb\datetime'); -		$user->lang = array( -			'FOO'		=> 'BAR', -			'BARZ'		=> 'PENG', -			'EMPTY'		=> '', -			'ZERO'		=> '0', -			'STR'		=> '%d %s, %d topics', -			'STR2'		=> '%d foos', -			'ARRY'		=> array( -				0		=> 'No posts',		// 0 -				1		=> '1 post',		// 1 -				2		=> '%d posts',		// 2+ -			), -			'ARRY_NO_ZERO'	=> array( -				1		=> '1 post',		// 1 -				2		=> '%d posts',		// 0, 2+ -			), -			'ARRY_MISSING'	=> array( -				1		=> '%d post',		// 1 -				//Missing second plural -			), -			'ARRY_FLOAT'	=> array( -				1		=> '1 post',		// 1.x -				2		=> '%1$.1f posts',	// 0.x, 2+.x -			), -			'ARRY_EMPTY'	=> array( -			), -			'dateformat'	=> array( -				'AGO'	=> array( -					1	=> '%d second', -					2	=> '%d seconds', -				), -			), -		); - -		// No param -		$this->assertEquals($user->lang('FOO'), 'BAR'); -		$this->assertEquals($user->lang('EMPTY'), ''); -		$this->assertEquals($user->lang('ZERO'), '0'); - -		// Invalid index -		$this->assertEquals($user->lang('VOID'), 'VOID'); - -		// Unnecessary param -		$this->assertEquals($user->lang('FOO', 2), 'BAR'); -		$this->assertEquals($user->lang('FOO', 2, 3), 'BAR'); -		$this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR'); - -		// String -		$this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics'); -		$this->assertEquals($user->lang('STR2', 64), '64 foos'); - -		// Array -		$this->assertEquals($user->lang('ARRY', 0), 'No posts'); -		$this->assertEquals($user->lang('ARRY', 1), '1 post'); -		$this->assertEquals($user->lang('ARRY', 2), '2 posts'); -		$this->assertEquals($user->lang('ARRY', 123), '123 posts'); - -		// Empty array returns the language key -		$this->assertEquals($user->lang('ARRY_EMPTY', 123), 'ARRY_EMPTY'); - -		// No 0 key defined -		$this->assertEquals($user->lang('ARRY_NO_ZERO', 0), '0 posts'); -		$this->assertEquals($user->lang('ARRY_NO_ZERO', 1), '1 post'); -		$this->assertEquals($user->lang('ARRY_NO_ZERO', 2), '2 posts'); - -		// Array with missing keys -		$this->assertEquals($user->lang('ARRY_MISSING', 2), '2 post'); - -		// Floats as array key -		$this->assertEquals($user->lang('ARRY_FLOAT', 1.3), '1 post'); -		$this->assertEquals($user->lang('ARRY_FLOAT', 2.0), '2.0 posts'); -		$this->assertEquals($user->lang('ARRY_FLOAT', 2.51), '2.5 posts'); - -		// Use sub key, if first paramenter is an array -		$this->assertEquals($user->lang(array('dateformat', 'AGO'), 2), '2 seconds'); - -		// ticket PHPBB3-9949 - use first int to determinate the plural-form to use -		$this->assertEquals($user->lang('ARRY', 1, 2), '1 post'); -		$this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post'); - -		// ticket PHPBB3-10345 - different plural rules, not just 0/1/2+ -		$user = new \phpbb\user('\phpbb\datetime'); -		$user->lang = array( -			'PLURAL_RULE'		=> 13, -			'ARRY'		=> array( -				0		=> '%d is 0',						// 0 -				1		=> '%d is 1',						// 1 -				2		=> '%d ends with 01-10',			// ending with 01-10 -				3		=> '%d ends with 11-19',			// ending with 11-19 -				4		=> '%d is part of the last rule',	// everything else -			), -		); -		$this->assertEquals($user->lang('ARRY', 0), '0 is 0'); -		$this->assertEquals($user->lang('ARRY', 1), '1 is 1'); -		$this->assertEquals($user->lang('ARRY', 103), '103 ends with 01-10'); -		$this->assertEquals($user->lang('ARRY', 15), '15 ends with 11-19'); -		$this->assertEquals($user->lang('ARRY', 300), '300 is part of the last rule'); -	} -} diff --git a/tests/user/user_loader_test.php b/tests/user/user_loader_test.php index 8d1f43707b..f871f324ca 100644 --- a/tests/user/user_loader_test.php +++ b/tests/user/user_loader_test.php @@ -11,8 +11,6 @@  *  */ -include_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php'); -  class phpbb_user_loader_test extends phpbb_database_test_case  {  	protected $db; diff --git a/tests/utf/normalizer_test.php b/tests/utf/normalizer_test.php deleted file mode 100644 index 50eafda859..0000000000 --- a/tests/utf/normalizer_test.php +++ /dev/null @@ -1,327 +0,0 @@ -<?php -/** -* -* This file is part of the phpBB Forum Software package. -* -* @copyright (c) phpBB Limited <https://www.phpbb.com> -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_normalizer.php'; - -/** -* @group slow -*/ -class phpbb_utf_normalizer_test extends phpbb_test_case -{ -	static private $data_dir; - -	static public function setUpBeforeClass() -	{ -		self::$data_dir = dirname(__file__) . '/../tmp'; -		self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', self::$data_dir); -		self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', self::$data_dir); -	} - -	public function test_normalizer() -	{ -		$test_suite = array( -			/** -			* NFC -			*   c2 ==  NFC(c1) ==  NFC(c2) ==  NFC(c3) -			*   c4 ==  NFC(c4) ==  NFC(c5) -			*/ -			'NFC'	=>	array( -				'c2'	=>	array('c1', 'c2', 'c3'), -				'c4'	=>	array('c4', 'c5') -			), - -			/** -			* NFD -			*   c3 ==  NFD(c1) ==  NFD(c2) ==  NFD(c3) -			*   c5 ==  NFD(c4) ==  NFD(c5) -			*/ -			'NFD'	=>	array( -				'c3'	=>	array('c1', 'c2', 'c3'), -				'c5'	=>	array('c4', 'c5') -			), - -			/** -			* NFKC -			*   c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5) -			*/ -			'NFKC'	=>	array( -				'c4'	=>	array('c1', 'c2', 'c3', 'c4', 'c5') -			), - -			/** -			* NFKD -			*   c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5) -			*/ -			'NFKD'	=>	array( -				'c5'	=>	array('c1', 'c2', 'c3', 'c4', 'c5') -			) -		); - -		$tested_chars = array(); - -		$fp = fopen(self::$data_dir . '/NormalizationTest.txt', 'rb'); -		while (!feof($fp)) -		{ -			$line = fgets($fp); - -			if ($line[0] == '@') -			{ -				continue; -			} - -			if (!strpos(' 0123456789ABCDEF', $line[0])) -			{ -				continue; -			} - -			list($c1, $c2, $c3, $c4, $c5) = explode(';', $line); - -			if (!strpos($c1, ' ')) -			{ -				/** -				* We are currently testing a single character, we add it to the list of -				* characters we have processed so that we can exclude it when testing -				* for invariants -				*/ -				$tested_chars[$c1] = 1; -			} - -			foreach ($test_suite as $form => $serie) -			{ -				foreach ($serie as $expected => $tests) -				{ -					$hex_expected = ${$expected}; -					$utf_expected = $this->hexseq_to_utf($hex_expected); - -					foreach ($tests as $test) -					{ -						$utf_result = $utf_expected; -						call_user_func_array(array('utf_normalizer', $form), array(&$utf_result)); - -						$hex_result = $this->utf_to_hexseq($utf_result); -						$this->assertEquals($utf_expected, $utf_result, "$expected == $form($test) ($hex_expected != $hex_result)"); -					} -				} -			} -		} -		fclose($fp); - -		return $tested_chars; -	} - -	/** -	* @depends test_normalizer -	*/ -	public function test_invariants(array $tested_chars) -	{ -		$fp = fopen(self::$data_dir . '/UnicodeData.txt', 'rb'); - -		while (!feof($fp)) -		{ -			$line = fgets($fp, 1024); - -			if (!$pos = strpos($line, ';')) -			{ -				continue; -			} - -			$hex_tested = $hex_expected = substr($line, 0, $pos); - -			if (isset($tested_chars[$hex_tested])) -			{ -				continue; -			} - -			$utf_expected = $this->hex_to_utf($hex_expected); - -			if ($utf_expected >= UTF8_SURROGATE_FIRST -			 && $utf_expected <= UTF8_SURROGATE_LAST) -			{ -				/** -				* Surrogates are illegal on their own, we expect the normalizer -				* to return a replacement char -				*/ -				$utf_expected = UTF8_REPLACEMENT; -				$hex_expected = $this->utf_to_hexseq($utf_expected); -			} - -			foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form) -			{ -				$utf_result = $utf_expected; -				call_user_func_array(array('utf_normalizer', $form), array(&$utf_result)); -				$hex_result = $this->utf_to_hexseq($utf_result); - -				$this->assertEquals($utf_expected, $utf_result, "$hex_expected == $form($hex_tested) ($hex_expected != $hex_result)"); -			} -		} -		fclose($fp); -	} - -	/** -	* Convert a UTF string to a sequence of codepoints in hexadecimal -	* -	* @param	string	$utf	UTF string -	* @return	integer			Unicode codepoints in hex -	*/ -	protected function utf_to_hexseq($str) -	{ -		$pos = 0; -		$len = strlen($str); -		$ret = array(); - -		while ($pos < $len) -		{ -			$c = $str[$pos]; -			switch ($c & "\xF0") -			{ -				case "\xC0": -				case "\xD0": -					$utf_char = substr($str, $pos, 2); -					$pos += 2; -					break; - -				case "\xE0": -					$utf_char = substr($str, $pos, 3); -					$pos += 3; -					break; - -				case "\xF0": -					$utf_char = substr($str, $pos, 4); -					$pos += 4; -					break; - -				default: -					$utf_char = $c; -					++$pos; -			} - -			$hex = dechex($this->utf_to_cp($utf_char)); - -			if (!isset($hex[3])) -			{ -				$hex = substr('000' . $hex, -4); -			} - -			$ret[] = $hex; -		} - -		return strtr(implode(' ', $ret), 'abcdef', 'ABCDEF'); -	} - -	/** -	* Convert a UTF-8 char to its codepoint -	* -	* @param	string	$utf_char	UTF-8 char -	* @return	integer				Unicode codepoint -	*/ -	protected function utf_to_cp($utf_char) -	{ -		switch (strlen($utf_char)) -		{ -			case 1: -				return ord($utf_char); - -			case 2: -				return ((ord($utf_char[0]) & 0x1F) << 6) | (ord($utf_char[1]) & 0x3F); - -			case 3: -				return ((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F); - -			case 4: -				return ((ord($utf_char[0]) & 0x07) << 18) | ((ord($utf_char[1]) & 0x3F) << 12) | ((ord($utf_char[2]) & 0x3F) << 6) | (ord($utf_char[3]) & 0x3F); - -			default: -				throw new RuntimeException('UTF-8 chars can only be 1-4 bytes long'); -		} -	} - -	/** -	* Return a UTF string formed from a sequence of codepoints in hexadecimal -	* -	* @param	string	$seq		Sequence of codepoints, separated with a space -	* @return	string				UTF-8 string -	*/ -	protected function hexseq_to_utf($seq) -	{ -		return implode('', array_map(array($this, 'hex_to_utf'), explode(' ', $seq))); -	} - -	/** -	* Convert a codepoint in hexadecimal to a UTF-8 char -	* -	* @param	string	$hex		Codepoint, in hexadecimal -	* @return	string				UTF-8 char -	*/ -	protected function hex_to_utf($hex) -	{ -		return $this->cp_to_utf(hexdec($hex)); -	} - -	/** -	* Convert a codepoint to a UTF-8 char -	* -	* @param	integer	$cp			Unicode codepoint -	* @return	string				UTF-8 string -	*/ -	protected function cp_to_utf($cp) -	{ -		if ($cp > 0xFFFF) -		{ -			return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); -		} -		else if ($cp > 0x7FF) -		{ -			return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); -		} -		else if ($cp > 0x7F) -		{ -			return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F)); -		} -		else -		{ -			return chr($cp); -		} -	} - -	// chunked download helper -	static protected function download($url, $to) -	{ -		$target = $to . '/' . basename($url); - -		if (file_exists($target)) -		{ -			return; -		} - -		if (!$fpr = fopen($url, 'rb')) -		{ -			echo "Failed to download $url\n"; -			return; -		} - -		if (!$fpw = fopen($target, 'wb')) -		{ -			echo "Failed to open $target for writing\n"; -			return; -		} - -		$chunk = 32768; - -		while (!feof($fpr)) -		{ -			fwrite($fpw, fread($fpr, $chunk)); -		} -		fclose($fpr); -		fclose($fpw); -	} -} diff --git a/tests/utf/utf8_clean_string_test.php b/tests/utf/utf8_clean_string_test.php index 2bb65387e0..4b3c8a5a25 100644 --- a/tests/utf/utf8_clean_string_test.php +++ b/tests/utf/utf8_clean_string_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_utf_utf8_clean_string_test extends phpbb_test_case  {  	public function cleanable_strings() diff --git a/tests/utf/utf8_wordwrap_test.php b/tests/utf/utf8_wordwrap_test.php index ab053e2911..8906595d33 100644 --- a/tests/utf/utf8_wordwrap_test.php +++ b/tests/utf/utf8_wordwrap_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; -  class phpbb_utf_utf8_wordwrap_test extends phpbb_test_case  {  	public function test_utf8_wordwrap_ascii() diff --git a/tests/version/version_fetch_test.php b/tests/version/version_fetch_test.php index cfc87183cf..6ecc9b7223 100644 --- a/tests/version/version_fetch_test.php +++ b/tests/version/version_fetch_test.php @@ -28,13 +28,15 @@ class phpbb_version_helper_fetch_test extends phpbb_test_case  			->disableOriginalConstructor()  			->getMock(); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +  		$this->version_helper = new \phpbb\version_helper(  			$this->cache,  			new \phpbb\config\config(array(  				'version'	=> '3.1.0',  			)),  			new \phpbb\file_downloader(), -			new \phpbb\user('\phpbb\datetime') +			new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime')  		);  	} diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php index 65ae7646b9..724c4c970c 100644 --- a/tests/version/version_helper_remote_test.php +++ b/tests/version/version_helper_remote_test.php @@ -30,20 +30,22 @@ class version_helper_remote_test extends \phpbb_test_case  		));  		$container = new \phpbb_mock_container_builder();  		$db = new \phpbb\db\driver\factory($container); -		$this->cache = $this->getMock('\phpbb\cache\service', array('get'), array(new \phpbb\cache\driver\null(), $config, $db, '../../', 'php')); +		$this->cache = $this->getMock('\phpbb\cache\service', array('get'), array(new \phpbb\cache\driver\dummy(), $config, $db, '../../', 'php'));  		$this->cache->expects($this->any())  			->method('get')  			->with($this->anything())  			->will($this->returnValue(false));  		$this->file_downloader = new phpbb_mock_file_downloader(); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +  		$this->version_helper = new \phpbb\version_helper(  			$this->cache,  			$config,  			$this->file_downloader, -			new \phpbb\user('\phpbb\datetime') +			new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime')  		); -		$this->user = new \phpbb\user('\phpbb\datetime'); +		$this->user = new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime');  		$this->user->add_lang('acp/common');  	} diff --git a/tests/version/version_test.php b/tests/version/version_test.php index 528f1602d6..05577f6a18 100644 --- a/tests/version/version_test.php +++ b/tests/version/version_test.php @@ -25,13 +25,15 @@ class phpbb_version_helper_test extends phpbb_test_case  			->disableOriginalConstructor()  			->getMock(); +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +  		$this->version_helper = new \phpbb\version_helper(  			$this->cache,  			new \phpbb\config\config(array(  				'version'	=> '3.1.0',  			)),  			new \phpbb\file_downloader(), -			new \phpbb\user('\phpbb\datetime') +			new \phpbb\user(new \phpbb\language\language($lang_loader), '\phpbb\datetime')  		);  	} @@ -199,6 +201,11 @@ class phpbb_version_helper_test extends phpbb_test_case  	*/  	public function test_get_suggested_updates($current_version, $versions, $expected)  	{ +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +  		$version_helper = $this  			->getMockBuilder('\phpbb\version_helper')  			->setMethods(array( @@ -210,7 +217,7 @@ class phpbb_version_helper_test extends phpbb_test_case  					'version'	=> $current_version,  				)),  				new \phpbb\file_downloader(), -				new \phpbb\user('\phpbb\datetime'), +				new \phpbb\user($lang, '\phpbb\datetime'),  			))  			->getMock()  		; @@ -310,6 +317,11 @@ class phpbb_version_helper_test extends phpbb_test_case  	*/  	public function test_get_latest_on_current_branch($current_version, $versions, $expected)  	{ +		global $phpbb_root_path, $phpEx; + +		$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx); +		$lang = new \phpbb\language\language($lang_loader); +  		$version_helper = $this  			->getMockBuilder('\phpbb\version_helper')  			->setMethods(array( @@ -321,7 +333,7 @@ class phpbb_version_helper_test extends phpbb_test_case  					'version'	=> $current_version,  				)),  				new \phpbb\file_downloader(), -				new \phpbb\user('\phpbb\datetime'), +				new \phpbb\user($lang, '\phpbb\datetime'),  			))  			->getMock()  		; diff --git a/tests/viewonline/helper_test.php b/tests/viewonline/helper_test.php index bbbed59de7..6540d33287 100644 --- a/tests/viewonline/helper_test.php +++ b/tests/viewonline/helper_test.php @@ -17,7 +17,7 @@ class phpbb_viewonline_helper_test extends phpbb_test_case  	{  		parent::setUp(); -		$this->viewonline_helper = new \phpbb\viewonline_helper(new \phpbb\filesystem()); +		$this->viewonline_helper = new \phpbb\viewonline_helper(new \phpbb\filesystem\filesystem());  	}  	public function session_pages_data() diff --git a/tests/wrapper/gmgetdate_test.php b/tests/wrapper/gmgetdate_test.php index 2e55a78d21..08ee491c0f 100644 --- a/tests/wrapper/gmgetdate_test.php +++ b/tests/wrapper/gmgetdate_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_wrapper_gmgetdate_test extends phpbb_test_case  {  	public static function phpbb_gmgetdate_data() diff --git a/tests/wrapper/mt_rand_test.php b/tests/wrapper/mt_rand_test.php index d190182286..8d370dee2a 100644 --- a/tests/wrapper/mt_rand_test.php +++ b/tests/wrapper/mt_rand_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_wrapper_mt_rand_test extends phpbb_test_case  {  	public function test_max_equals_min() diff --git a/tests/wrapper/phpbb_php_ini_fake.php b/tests/wrapper/phpbb_php_ini_fake.php index f218ff6d03..300ce30cfe 100644 --- a/tests/wrapper/phpbb_php_ini_fake.php +++ b/tests/wrapper/phpbb_php_ini_fake.php @@ -11,7 +11,7 @@  *  */ -class phpbb_php_ini_fake extends \phpbb\php\ini +class phpbb_php_ini_fake extends \bantu\IniGetWrapper\IniGetWrapper  {  	function get($varname)  	{ diff --git a/tests/wrapper/phpbb_php_ini_test.php b/tests/wrapper/phpbb_php_ini_test.php index 27c2487f0a..5827744702 100644 --- a/tests/wrapper/phpbb_php_ini_test.php +++ b/tests/wrapper/phpbb_php_ini_test.php @@ -12,10 +12,10 @@  */  require_once dirname(__FILE__) . '/phpbb_php_ini_fake.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';  class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case  { +	/** @var \phpbb_php_ini_fake php_ini */  	protected $php_ini;  	public function setUp() @@ -25,44 +25,44 @@ class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case  	public function test_get_string()  	{ -		$this->assertSame(false, $this->php_ini->get_string(false)); -		$this->assertSame('phpbb', $this->php_ini->get_string(' phpbb ')); +		$this->assertSame('', $this->php_ini->getString(false)); +		$this->assertSame('phpbb', $this->php_ini->getString(' phpbb '));  	}  	public function test_get_bool()  	{ -		$this->assertSame(true, $this->php_ini->get_bool('ON')); -		$this->assertSame(true, $this->php_ini->get_bool('on')); -		$this->assertSame(true, $this->php_ini->get_bool('1')); +		$this->assertSame(true, $this->php_ini->getBool('ON')); +		$this->assertSame(true, $this->php_ini->getBool('on')); +		$this->assertSame(true, $this->php_ini->getBool('1')); -		$this->assertSame(false, $this->php_ini->get_bool('OFF')); -		$this->assertSame(false, $this->php_ini->get_bool('off')); -		$this->assertSame(false, $this->php_ini->get_bool('0')); -		$this->assertSame(false, $this->php_ini->get_bool('')); +		$this->assertSame(false, $this->php_ini->getBool('OFF')); +		$this->assertSame(false, $this->php_ini->getBool('off')); +		$this->assertSame(false, $this->php_ini->getBool('0')); +		$this->assertSame(false, $this->php_ini->getBool(''));  	}  	public function test_get_int()  	{ -		$this->assertSame(1234, $this->php_ini->get_int('1234')); -		$this->assertSame(-12345, $this->php_ini->get_int('-12345')); -		$this->assertSame(false, $this->php_ini->get_int('phpBB')); +		$this->assertSame(1234, $this->php_ini->getNumeric('1234')); +		$this->assertSame(-12345, $this->php_ini->getNumeric('-12345')); +		$this->assertSame(null, $this->php_ini->getNumeric('phpBB'));  	}  	public function test_get_float()  	{ -		$this->assertSame(1234.0, $this->php_ini->get_float('1234')); -		$this->assertSame(-12345.0, $this->php_ini->get_float('-12345')); -		$this->assertSame(false, $this->php_ini->get_float('phpBB')); +		$this->assertSame(1234.0, $this->php_ini->getNumeric('1234.0')); +		$this->assertSame(-12345.0, $this->php_ini->getNumeric('-12345.0')); +		$this->assertSame(null, $this->php_ini->getNumeric('phpBB'));  	}  	public function test_get_bytes_invalid()  	{ -		$this->assertSame(false, $this->php_ini->get_bytes(false)); -		$this->assertSame(false, $this->php_ini->get_bytes('phpBB')); -		$this->assertSame(false, $this->php_ini->get_bytes('k')); -		$this->assertSame(false, $this->php_ini->get_bytes('-k')); -		$this->assertSame(false, $this->php_ini->get_bytes('M')); -		$this->assertSame(false, $this->php_ini->get_bytes('-M')); +		$this->assertSame(null, $this->php_ini->getBytes(false)); +		$this->assertSame(null, $this->php_ini->getBytes('phpBB')); +		$this->assertSame(null, $this->php_ini->getBytes('k')); +		$this->assertSame(null, $this->php_ini->getBytes('-k')); +		$this->assertSame(null, $this->php_ini->getBytes('M')); +		$this->assertSame(null, $this->php_ini->getBytes('-M'));  	}  	/** @@ -70,7 +70,7 @@ class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case  	*/  	public function test_get_bytes($expected, $value)  	{ -		$actual = $this->php_ini->get_bytes($value); +		$actual = $this->php_ini->getBytes($value);  		$this->assertTrue(is_float($actual) || is_int($actual));  		$this->assertEquals($expected, $actual); diff --git a/tests/wrapper/version_compare_test.php b/tests/wrapper/version_compare_test.php index 93d9e0117d..8260d99504 100644 --- a/tests/wrapper/version_compare_test.php +++ b/tests/wrapper/version_compare_test.php @@ -11,8 +11,6 @@  *  */ -require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; -  class phpbb_wrapper_version_compare_test extends phpbb_test_case  {  	public function test_two_parameters()  | 
