<?php
/*
 * Copyright (c) 2012, webvariants GbR, http://www.webvariants.de
 *
 * This file is released under the terms of the MIT license. You can find the
 * complete text in the attached LICENSE file or online at:
 *
 * http://www.opensource.org/licenses/mit-license.php
 */

class RealURL2_GeneratorTest extends RealURL2_BaseTest {
	/**
	 * @dataProvider startArticleProvider
	 */
	public function testBuildSiteStartArticleUrl($clang, $expected) {
		$cache = new _WV24_RuntimeCache();
		$cache->prewarmForSiteStartArticle($clang);

		$generator = new _WV24_Generator($cache);
		$this->assertEquals($expected, $generator->buildUrl(98, $clang));

		$cache = new _WV24_RuntimeCache();
		$cache->prewarmForSiteStartArticle($clang);

		$generator = new _WV24_Generator($cache);
		$this->assertEquals($expected, $generator->buildSiteStartUrl($clang));
	}

	public function startArticleProvider() {
		return array(array(5, 'http://cli/'), array(8, 'http://cli/en/'));
	}

	/**
	 * @depends      testBuildSiteStartArticleUrl
	 * @dataProvider deeperSiteStartProvider
	 */
	public function testDeeperSiteStartArticle($article, $clang, $expected) {
		// (Home) > C64 > Hardware
		sly_Core::config()->set('START_ARTICLE_ID', 2);

		$cache = new _WV24_RuntimeCache();
		$path  = sly_DB_Persistence::getInstance()->magicFetch('article', 'path', array('id' => $article, 'clang' => $clang));

		$cache->prewarmForArticle($article, $clang, $path);

		$generator = new _WV24_Generator($cache);
		$this->assertEquals($expected, $generator->buildUrl($article, $clang));
	}

	public function deeperSiteStartProvider() {
		return array(
			array(2,   5, 'http://cli/'),
			array(90,  5, 'http://cli/ackermannfunktion.html'),
			array(48,  5, 'http://cli/c64/'),
			array(1,   5, 'http://cli/c64/entwicklung/'),
			array(49,  5, 'http://cli/computervirus/'),
			array(15,  5, 'http://cli/prozessor/'),
			array(101, 5, 'http://cli/deutsch-ist-auch-mal-toll.html'),
			array(102, 5, 'http://cli/prozessor/x86-ftw.html'),

			array(2,   8, 'http://cli/en/'),
			array(90,  8, 'http://cli/en/Ackermann+function.html'),
			array(48,  8, 'http://cli/en/C64/'),
			array(1,   8, 'http://cli/en/C64/'.urlencode('发展').'/'),
			array(49,  8, 'http://cli/en/Computer+virus/'),
			array(15,  8, 'http://cli/en/Prozessor/'),
			array(101, 8, 'http://cli/en/Deutsch+ist+auch+mal+toll.html'),
			array(102, 8, 'http://cli/en/Prozessor/x86+FTW.html')
		);
	}

	/**
	 * @dataProvider rootArticleProvider
	 * @depends      testBuildSiteStartArticleUrl
	 */
	public function testBuildRootArticleUrl($clang, $expected) {
		$cache = new _WV24_RuntimeCache();
		$cache->prewarmForArticle(90, $clang);

		$generator = new _WV24_Generator($cache);
		$this->assertEquals($expected, $generator->buildUrl(90, $clang));
	}

	public function rootArticleProvider() {
		return array(array(5, 'http://cli/ackermannfunktion.html'), array(8, 'http://cli/en/Ackermann+function.html'));
	}

	/**
	 * @dataProvider rootCategoryProvider
	 * @depends      testBuildRootArticleUrl
	 */
	public function testBuildRootCategoryUrl($clang, $expected) {
		$cache = new _WV24_RuntimeCache();
		$cache->prewarmForArticle(49, $clang);

		$generator = new _WV24_Generator($cache);
		$this->assertEquals($expected, $generator->buildUrl(49, $clang));
	}

	public function rootCategoryProvider() {
		return array(array(5, 'http://cli/computervirus/'), array(8, 'http://cli/en/Computer+virus/'));
	}

	/**
	 * @dataProvider arbitraryProvider
	 * @depends      testBuildRootCategoryUrl
	 */
	public function testBuildArbitraryUrl($id, $clang, $expected, $cleanup = null, $lower = null) {
		if ($cleanup !== null) $this->setConfigValue('cleanup',   $cleanup ? '1' : '0', $clang);
		if ($lower !== null)   $this->setConfigValue('lowercase', $lower ? '1' : '0',   $clang);

		$path  = sly_DB_Persistence::getInstance()->magicFetch('article', 'path', array('id' => $id, 'clang' => $clang));
		$cache = new _WV24_RuntimeCache();
		$cache->prewarmForArticle($id, $clang, $path);

		$generator = new _WV24_Generator($cache);
		$this->assertEquals($expected, $generator->buildUrl($id, $clang));
	}

	public function arbitraryProvider() {
		return array(
			array(1, 5,  'http://cli/c64/entwicklung/'),
			array(20, 5, 'http://cli/c64/peripherie/laufwerke/'),
			array(23, 5, 'http://cli/c64/peripherie/dfue-geraete/'),
			array(50, 8, 'http://cli/en/Computer+virus/Infection+strategies/'),
			array(50, 8, 'http://cli/en/Computer-virus/Infection-strategies/', true),
			array(50, 8, 'http://cli/en/computer-virus/infection-strategies/', true, true),
			array(50, 8, 'http://cli/en/computer+virus/infection+strategies/', null, true),
			array(2, 8,  'http://cli/en/C64/'.urlencode('硬件 hardware').'/'),
			array(18, 8, 'http://cli/en/C64/'.urlencode('硬件 hardware').'/Grafik/'),
			array(18, 8, 'http://cli/en/C64/hardware/Grafik/', true),
			array(1, 8,  'http://cli/en/C64/'.urlencode('发展').'/'),
			array(1, 8,  'http://cli/en/C64/unbenannte-kategorie/', true),
			array(1, 8,  'http://cli/en/c64/'.urlencode('发展').'/', null, true),
			array(1, 8,  'http://cli/en/c64/unbenannte-kategorie/', true, true),
		);
	}

	/**
	 * @depends testBuildArbitraryUrl
	 */
	public function testBuildCompleteCache() {
		$cache     = new _WV24_RuntimeCache();
		$tree      = WV24_Util::getTree(null);
		$clangs    = sly_Util_Language::findAll(true);
		$generator = new _WV24_Generator($cache);
		$storage   = WV24_Util::getStorage();

		foreach ($clangs as $clang) {
			// prewarm
			$cache->prewarmAll($clang);

			// generate the URLs
			$urls = array();

			foreach ($tree as $id => $path) {
				$urls[] = array(
					'ident'      => $id.'_'.$clang,
					'article_id' => $id,
					'clang'      => $clang,
					'path'       => $path,
					'url'        => $generator->buildUrl($id, $clang)
				);
			}

			// and store them
			$storage->setMany(WV24_RealURL2::URL_NAMESPACE, $urls);
		}

		$articles = sly_DB_Persistence::getInstance()->magicFetch('article', 'COUNT(*)');
		$urls     = sly_DB_Persistence::getInstance()->magicFetch('wv24_urls', 'COUNT(*)');

		$this->assertEquals($articles, $urls);
	}

	/**
	 * @depends      testBuildArbitraryUrl
	 * @dataProvider fragmentsProvider
	 */
	public function testFragments($clang, array $fragments, array $expectations, $startArticle = null) {
		if ($startArticle !== null) {
			sly_Core::config()->set('START_ARTICLE_ID', $startArticle);
		}

		$db = sly_DB_Persistence::getInstance();

		foreach ($fragments as $id => $fragment) {
			if (strpos($fragment, '|') !== false) {
				$parts = explode('|', $fragment);
				$what  = array('wv24_fragment' => $parts[0], 'wv24_skip' => $parts[1]);
			}
			else {
				$what = array('wv24_fragment' => $fragment);
			}

			$db->update('article', $what, array('id' => $id, 'clang' => $clang));
		}

		foreach ($expectations as $id => $url) {
			$path  = $db->magicFetch('article', 'path', array('id' => $id, 'clang' => $clang));
			$cache = new _WV24_RuntimeCache();
			$cache->prewarmForArticle($id, $clang, $path);

			$generator = new _WV24_Generator($cache);
			$this->assertEquals($url, $generator->buildUrl($id, $clang));
		}
	}

	public function fragmentsProvider() {
		return array(
			// easy alias
			array(5, array(90 => 'test.html'),           array(90 => 'http://cli/test.html')),
			array(5, array(1 => 'entwickeln'),           array(1 => 'http://cli/c64/entwickeln', 99 => 'http://cli/c64/entwickeln/test-foo.html')),

			// easy absolute fragment
			array(5, array(90 => '/foo'),                array(90 => 'http://cli/foo')),
			array(5, array(2 => '/hart'),                array(2 => 'http://cli/hart', 101 => 'http://cli/hart/deutsch-ist-auch-mal-toll.html')),

			// yep, by giving fragments you can create conflicts
			array(5, array(90 => '/'),                   array(90 => 'http://cli/', 98 => 'http://cli/')),

			// fragments should be applied 1:1
			array(5, array(90 => '/bla/Foo.html'),       array(90 => 'http://cli/bla/Foo.html')),

			// re-route category should affect all children
			array(5, array(48 => '/toaster'),            array(48 => 'http://cli/toaster', 1 => 'http://cli/toaster/entwicklung/', 99 => 'http://cli/toaster/entwicklung/test-foo.html')),
			array(5, array(48 => '/toaster.html'),       array(48 => 'http://cli/toaster.html', 1 => 'http://cli/toaster.html/entwicklung/')),

			// ignore fragment of start article
			array(5, array(98 => '/dontcare'),           array(98 => 'http://cli/')),

			// multiple absolute fragments
			array(5, array(15 => '/proz', 2 => '/hart'), array(
				15  => 'http://cli/proz',
				2   => 'http://cli/hart',
				101 => 'http://cli/hart/deutsch-ist-auch-mal-toll.html',
				102 => 'http://cli/proz/x86-ftw.html'
			)),

			array(5, array(15 => '/', 2 => '/hart'), array(
				15  => 'http://cli/',
				2   => 'http://cli/hart',
				101 => 'http://cli/hart/deutsch-ist-auch-mal-toll.html',
				102 => 'http://cli/x86-ftw.html'
			)),

			array(5, array(48 => '/a', 49 => '/a'), array(
				48 => 'http://cli/a',
				49 => 'http://cli/a',
				2  => 'http://cli/a/hardware/',
				50 => 'http://cli/a/arbeitsweise/'
			)),

			// test if the default fragment is always fully copied (does not override the '/en' in the global settings)
			array(8, array(90 => '/foo'),    array(90 => 'http://cli/en/foo')),
			array(8, array(1 => '/wickeln'), array(1 => 'http://cli/en/wickeln')),

			// and now test domain fragments
			array(5, array(90 => '//example.com/article.html'), array(
				98 => 'http://cli/',
				90 => 'http://example.com/article.html'
			)),

			array(8, array(48 => '//c64.com/english'), array(
				90 => 'http://cli/en/Ackermann+function.html',
				98 => 'http://cli/en/',
				48 => 'http://c64.com/english',
				1  => 'http://c64.com/english/'.urlencode('发展').'/'
			)),

			// nested domain and absolute fragments
			array(5, array(48 => '//c64.com', 2 => '/hart', 15 => '/proz'), array(
				48  => 'http://c64.com/',
				2   => 'http://c64.com/hart',
				101 => 'http://c64.com/hart/deutsch-ist-auch-mal-toll.html',
				15  => 'http://c64.com/proz',
				102 => 'http://c64.com/proz/x86-ftw.html'
			)),

			// nested domain fragments
			array(5, array(48 => '//c64.com', 2 => '/hart', 15 => '//proz.c64.com'), array(
				48  => 'http://c64.com/',
				2   => 'http://c64.com/hart',
				101 => 'http://c64.com/hart/deutsch-ist-auch-mal-toll.html',
				15  => 'http://proz.c64.com/',
				102 => 'http://proz.c64.com/x86-ftw.html'
			)),

			// skipping levels (wv24_skip)
			array(5, array(48 => '|1'),                      array(48 => 'http://cli/c64/', 1 => 'http://cli/entwicklung/')),
			array(5, array(48 => '|1', 1 => '|1'),           array(48 => 'http://cli/c64/', 1 => 'http://cli/entwicklung/', 99 => 'http://cli/test-foo.html')),
			array(5, array(1 => '|1'),                       array(48 => 'http://cli/c64/', 1 => 'http://cli/c64/entwicklung/', 2 => 'http://cli/c64/hardware/', 99 => 'http://cli/c64/test-foo.html')),

			// skipping on site start article
			array(5, array(2 => '|1'),                       array(2 => 'http://cli/', 15 => 'http://cli/c64/prozessor/', 1 => 'http://cli/c64/entwicklung/'), 2),
			array(5, array(2 => '|1', 48 => '|1'),           array(2 => 'http://cli/', 15 => 'http://cli/prozessor/', 1 => 'http://cli/entwicklung/', 48 => 'http://cli/c64/'), 2),

			// skipping and aliase
			array(5, array(48 => 'c128|1'),                  array(48 => 'http://cli/c128', 1 => 'http://cli/entwicklung/', 2 => 'http://cli/hardware/')),
			array(5, array(2 => 'hart|1'),                   array(48 => 'http://cli/c64/', 1 => 'http://cli/c64/entwicklung/', 2 => 'http://cli/c64/hart', 15 => 'http://cli/c64/prozessor/')),

			// skipping and absolute fragments
			array(5, array(2 => '/hart|1'),                  array(48 => 'http://cli/c64/', 1 => 'http://cli/c64/entwicklung/', 2 => 'http://cli/hart', 15 => 'http://cli/c64/prozessor/')),
			array(5, array(48 => '/c128|1'),                 array(48 => 'http://cli/c128', 1 => 'http://cli/entwicklung/', 2 => 'http://cli/hardware/')),
			array(5, array(48 => '/c128|1', 2 => '/hart|1'), array(48 => 'http://cli/c128', 1 => 'http://cli/entwicklung/', 2 => 'http://cli/hart', 15 => 'http://cli/prozessor/')),

			// let's double check that the 'walk parent and ignore skipped levels'-algorithm doesn't also ignore the start article
			array(5, array(48 => '/c128|1', 2 => '/hart|1', 98 => '/ignore|1'), array(48 => 'http://cli/c128', 1 => 'http://cli/entwicklung/', 2 => 'http://cli/hart', 15 => 'http://cli/prozessor/', 98 => 'http://cli/')),

			// skipping and domain fragments (domains should never be skipped)
			array(5, array(2 => '//hart.com|1'),                  array(48 => 'http://cli/c64/', 1 => 'http://cli/c64/entwicklung/', 2 => 'http://hart.com/', 15 => 'http://hart.com/prozessor/')),
			array(5, array(48 => '//c64|1'),                      array(48 => 'http://c64/', 1 => 'http://c64/entwicklung/', 2 => 'http://c64/hardware/')),
			array(5, array(48 => '//c64|1', 2 => '//hart.com|1'), array(48 => 'http://c64/', 1 => 'http://c64/entwicklung/', 2 => 'http://hart.com/', 15 => 'http://hart.com/prozessor/')),

			// mixing skips, domain and absolute fragments
			array(5, array(
				48 => '/c64|1',
				2  => '//hart.com|1',
				4  => '//perimeter.com',
				20 => '|1',
				21 => '/eingabe'
			), array(
				98  => 'http://cli/',
				48  => 'http://cli/c64',
				1   => 'http://cli/entwicklung/',
				2   => 'http://hart.com/',
				15  => 'http://hart.com/prozessor/',
				101 => 'http://hart.com/deutsch-ist-auch-mal-toll.html',
				4   => 'http://perimeter.com/',
				20  => 'http://perimeter.com/laufwerke/',
				25  => 'http://perimeter.com/kassettenlaufwerk-1530/',
				21  => 'http://perimeter.com/eingabe'
			)),
		);
	}
}
